We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use a different colour for waiting list events
### Is your feature request related to a problem? Please describe.
In the event overview calendar, the dot in front of the event is colored as if you are registered. And this is confusing.

### Describe the solution you'd like
Use a different colour for events you're on the waiting list for.

### Motivation
Better user experience.

### Describe alternatives you've considered
There is not really any alternative

### Additional context
Created based on #1007


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `website/events/api/calendarjs/serializers.py`
Content:
```
1 from rest_framework.reverse import reverse
2 
3 from events import services
4 from events.models import Event
5 from thaliawebsite.api.calendarjs.serializers import CalenderJSSerializer
6 
7 
8 class EventsCalenderJSSerializer(CalenderJSSerializer):
9     class Meta(CalenderJSSerializer.Meta):
10         model = Event
11 
12     def _url(self, instance):
13         return reverse("events:event", kwargs={"pk": instance.id})
14 
15     def _class_names(self, instance):
16         class_names = ["regular-event"]
17         if self.context["member"] and services.is_user_registered(
18             self.context["member"], instance
19         ):
20             class_names.append("has-registration")
21         return class_names
22 
23 
24 class UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):
25     """See CalenderJSSerializer, customised classes."""
26 
27     class Meta(CalenderJSSerializer.Meta):
28         model = Event
29 
30     def _class_names(self, instance):
31         return ["unpublished-event"]
32 
33     def _url(self, instance):
34         return reverse("admin:events_event_details", kwargs={"pk": instance.id})
35
```

Path: `website/events/services.py`
Content:
```
1 from collections import OrderedDict
2 
3 from django.utils import timezone
4 from django.utils.datetime_safe import date
5 from django.utils.translation import gettext_lazy as _, get_language
6 
7 from events import emails
8 from events.exceptions import RegistrationError
9 from events.models import EventRegistration, RegistrationInformationField, Event
10 from payments.api.v1.fields import PaymentTypeField
11 from payments.services import create_payment, delete_payment
12 from utils.snippets import datetime_to_lectureyear
13 
14 
15 def is_user_registered(member, event):
16     """Return if the user is registered for the specified event.
17 
18     :param member: the user
19     :param event: the event
20     :return: None if registration is not required or no member else True/False
21     """
22     if not event.registration_required or not member.is_authenticated:
23         return None
24 
25     return event.registrations.filter(member=member, date_cancelled=None).count() > 0
26 
27 
28 def is_user_present(member, event):
29     if not event.registration_required or not member.is_authenticated:
30         return None
31 
32     return (
33         event.registrations.filter(
34             member=member, date_cancelled=None, present=True
35         ).count()
36         > 0
37     )
38 
39 
40 def event_permissions(member, event, name=None):
41     """Return a dictionary with the available event permissions of the user.
42 
43     :param member: the user
44     :param event: the event
45     :param name: the name of a non member registration
46     :return: the permission dictionary
47     """
48     perms = {
49         "create_registration": False,
50         "cancel_registration": False,
51         "update_registration": False,
52         "manage_event": is_organiser(member, event),
53     }
54     if not member:
55         return perms
56     if not (member.is_authenticated or name):
57         return perms
58 
59     registration = None
60     try:
61         registration = EventRegistration.objects.get(
62             event=event, member=member, name=name
63         )
64     except EventRegistration.DoesNotExist:
65         pass
66 
67     perms["create_registration"] = (
68         (registration is None or registration.date_cancelled is not None)
69         and (event.registration_allowed or not event.registration_required)
70         and (name or member.can_attend_events)
71     )
72     perms["cancel_registration"] = (
73         registration is not None
74         and registration.date_cancelled is None
75         and (event.cancellation_allowed or name or not event.registration_required)
76         and registration.payment is None
77     )
78     perms["update_registration"] = (
79         registration is not None
80         and registration.date_cancelled is None
81         and event.has_fields
82         and (event.registration_allowed or not event.registration_required)
83         and (name or member.can_attend_events)
84     )
85     return perms
86 
87 
88 def is_organiser(member, event):
89     if member and member.is_authenticated:
90         if member.is_superuser or member.has_perm("events.override_organiser"):
91             return True
92 
93         if event:
94             return member.get_member_groups().filter(pk=event.organiser.pk).count() != 0
95 
96     return False
97 
98 
99 def create_registration(member, event):
100     """Create a new user registration for an event.
101 
102     :param member: the user
103     :param event: the event
104     :return: Return the registration if successful
105     """
106     if event_permissions(member, event)["create_registration"]:
107         registration = None
108         try:
109             registration = EventRegistration.objects.get(event=event, member=member)
110         except EventRegistration.DoesNotExist:
111             pass
112 
113         if registration is None:
114             return EventRegistration.objects.create(event=event, member=member)
115         if registration.date_cancelled is not None:
116             if registration.is_late_cancellation():
117                 raise RegistrationError(
118                     _(
119                         "You cannot re-register anymore "
120                         "since you've cancelled after the "
121                         "deadline."
122                     )
123                 )
124             registration.date = timezone.now()
125             registration.date_cancelled = None
126             registration.save()
127 
128         return registration
129     if event_permissions(member, event)["cancel_registration"]:
130         raise RegistrationError(_("You were already registered."))
131     raise RegistrationError(_("You may not register."))
132 
133 
134 def cancel_registration(member, event):
135     """Cancel a user registration for an event.
136 
137     :param member: the user
138     :param event: the event
139     """
140     registration = None
141     try:
142         registration = EventRegistration.objects.get(event=event, member=member)
143     except EventRegistration.DoesNotExist:
144         pass
145 
146     if event_permissions(member, event)["cancel_registration"] and registration:
147         if not registration.queue_position:
148             emails.notify_first_waiting(event)
149 
150             if event.send_cancel_email and event.after_cancel_deadline:
151                 emails.notify_organiser(event, registration)
152 
153         # Note that this doesn"t remove the values for the
154         # information fields that the user entered upon registering.
155         # But this is regarded as a feature, not a bug. Especially
156         # since the values will still appear in the backend.
157         registration.date_cancelled = timezone.now()
158         registration.save()
159     else:
160         raise RegistrationError(_("You are not allowed to deregister for this event."))
161 
162 
163 def update_registration(
164     member=None, event=None, name=None, registration=None, field_values=None
165 ):
166     """Update a user registration of an event.
167 
168     :param request: http request
169     :param member: the user
170     :param event: the event
171     :param name: the name of a registration not associated with a user
172     :param registration: the registration
173     :param field_values: values for the information fields
174     """
175     if not registration:
176         try:
177             registration = EventRegistration.objects.get(
178                 event=event, member=member, name=name
179             )
180         except EventRegistration.DoesNotExist as error:
181             raise RegistrationError(
182                 _("You are not registered for this event.")
183             ) from error
184     else:
185         member = registration.member
186         event = registration.event
187         name = registration.name
188 
189     if (
190         not event_permissions(member, event, name)["update_registration"]
191         or not field_values
192     ):
193         return
194 
195     for field_id, field_value in field_values:
196         field = RegistrationInformationField.objects.get(
197             id=field_id.replace("info_field_", "")
198         )
199 
200         if (
201             field.type == RegistrationInformationField.INTEGER_FIELD
202             and field_value is None
203         ):
204             field_value = 0
205         elif (
206             field.type == RegistrationInformationField.BOOLEAN_FIELD
207             and field_value is None
208         ):
209             field_value = False
210         elif (
211             field.type == RegistrationInformationField.TEXT_FIELD
212             and field_value is None
213         ):
214             field_value = ""
215 
216         field.set_value_for(registration, field_value)
217 
218 
219 def registration_fields(request, member=None, event=None, registration=None, name=None):
220     """Return information about the registration fields of a registration.
221 
222     :param member: the user (optional if registration provided)
223     :param name: the name of a non member registration
224                  (optional if registration provided)
225     :param event: the event (optional if registration provided)
226     :param registration: the registration (optional if member & event provided)
227     :return: the fields
228     """
229     if registration is None:
230         try:
231             registration = EventRegistration.objects.get(
232                 event=event, member=member, name=name
233             )
234         except EventRegistration.DoesNotExist as error:
235             raise RegistrationError(
236                 _("You are not registered for this event.")
237             ) from error
238         except EventRegistration.MultipleObjectsReturned as error:
239             raise RegistrationError(
240                 _("Unable to find the right registration.")
241             ) from error
242 
243     member = registration.member
244     event = registration.event
245     name = registration.name
246 
247     perms = event_permissions(member, event, name)[
248         "update_registration"
249     ] or is_organiser(request.member, event)
250     if perms and registration:
251         information_fields = registration.information_fields
252         fields = OrderedDict()
253 
254         for information_field in information_fields:
255             field = information_field["field"]
256 
257             fields["info_field_{}".format(field.id)] = {
258                 "type": field.type,
259                 "label": getattr(field, "{}_{}".format("name", get_language())),
260                 "description": getattr(
261                     field, "{}_{}".format("description", get_language())
262                 ),
263                 "value": information_field["value"],
264                 "required": field.required,
265             }
266 
267         return fields
268     raise RegistrationError(_("You are not allowed to update this registration."))
269 
270 
271 def update_registration_by_organiser(registration, member, data):
272     if not is_organiser(member, registration.event):
273         raise RegistrationError(_("You are not allowed to update this registration."))
274 
275     if "payment" in data:
276         if data["payment"]["type"] == PaymentTypeField.NO_PAYMENT:
277             if registration.payment is not None:
278                 delete_payment(registration)
279         else:
280             registration.payment = create_payment(
281                 payable=registration,
282                 processed_by=member,
283                 pay_type=data["payment"]["type"],
284             )
285 
286     if "present" in data:
287         registration.present = data["present"]
288 
289     registration.save()
290 
291 
292 def generate_category_statistics():
293     """Generate statistics about events, number of events per category.
294 
295     :return: Dict with key, value resp. being category, event count.
296     """
297     year = datetime_to_lectureyear(timezone.now())
298 
299     data = {}
300     for i in range(5):
301         year_start = date(year=year - i, month=9, day=1)
302         year_end = date(year=year - i + 1, month=9, day=1)
303         data[str(year - i)] = {
304             str(display): Event.objects.filter(
305                 category=key, start__gte=year_start, end__lte=year_end
306             ).count()
307             for key, display in Event.EVENT_CATEGORIES
308         }
309 
310     return data
311
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/website/events/api/calendarjs/serializers.py b/website/events/api/calendarjs/serializers.py
--- a/website/events/api/calendarjs/serializers.py
+++ b/website/events/api/calendarjs/serializers.py
@@ -13,12 +13,18 @@
         return reverse("events:event", kwargs={"pk": instance.id})
 
     def _class_names(self, instance):
-        class_names = ["regular-event"]
         if self.context["member"] and services.is_user_registered(
             self.context["member"], instance
         ):
-            class_names.append("has-registration")
-        return class_names
+            if services.user_registration_pending(self.context["member"], instance):
+                return ["regular-event-pending-registration"]
+            else:
+                return ["regular-event-has-registration"]
+        elif (not instance.registration_required) or instance.registration_allowed:
+            return ["regular-event-registration-open"]
+        else:
+            # I think this handles the case that registration is needed, but not yet possible
+            return ["regular-event-registration-closed"]
 
 
 class UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):
diff --git a/website/events/services.py b/website/events/services.py
--- a/website/events/services.py
+++ b/website/events/services.py
@@ -19,12 +19,28 @@
     :param event: the event
     :return: None if registration is not required or no member else True/False
     """
-    if not event.registration_required or not member.is_authenticated:
+    if not member.is_authenticated:
         return None
 
     return event.registrations.filter(member=member, date_cancelled=None).count() > 0
 
 
+def user_registration_pending(member, event):
+    """Return if the user is in the queue, but not yet registered for, the specific event.
+
+    :param member: the user
+    :param event: the event
+    :return: None if registration is not required or no member else True/False
+    """
+    if not event.registration_required:
+        return False
+    if not member.is_authenticated:
+        return None
+
+    reg = event.registrations.filter(member=member, date_cancelled=None)
+    return len(list(filter(lambda r: r.queue_position, reg))) > 0
+
+
 def is_user_present(member, event):
     if not event.registration_required or not member.is_authenticated:
         return None

{"golden_diff": "diff --git a/website/events/api/calendarjs/serializers.py b/website/events/api/calendarjs/serializers.py\n--- a/website/events/api/calendarjs/serializers.py\n+++ b/website/events/api/calendarjs/serializers.py\n@@ -13,12 +13,18 @@\n         return reverse(\"events:event\", kwargs={\"pk\": instance.id})\n \n     def _class_names(self, instance):\n-        class_names = [\"regular-event\"]\n         if self.context[\"member\"] and services.is_user_registered(\n             self.context[\"member\"], instance\n         ):\n-            class_names.append(\"has-registration\")\n-        return class_names\n+            if services.user_registration_pending(self.context[\"member\"], instance):\n+                return [\"regular-event-pending-registration\"]\n+            else:\n+                return [\"regular-event-has-registration\"]\n+        elif (not instance.registration_required) or instance.registration_allowed:\n+            return [\"regular-event-registration-open\"]\n+        else:\n+            # I think this handles the case that registration is needed, but not yet possible\n+            return [\"regular-event-registration-closed\"]\n \n \n class UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):\ndiff --git a/website/events/services.py b/website/events/services.py\n--- a/website/events/services.py\n+++ b/website/events/services.py\n@@ -19,12 +19,28 @@\n     :param event: the event\n     :return: None if registration is not required or no member else True/False\n     \"\"\"\n-    if not event.registration_required or not member.is_authenticated:\n+    if not member.is_authenticated:\n         return None\n \n     return event.registrations.filter(member=member, date_cancelled=None).count() > 0\n \n \n+def user_registration_pending(member, event):\n+    \"\"\"Return if the user is in the queue, but not yet registered for, the specific event.\n+\n+    :param member: the user\n+    :param event: the event\n+    :return: None if registration is not required or no member else True/False\n+    \"\"\"\n+    if not event.registration_required:\n+        return False\n+    if not member.is_authenticated:\n+        return None\n+\n+    reg = event.registrations.filter(member=member, date_cancelled=None)\n+    return len(list(filter(lambda r: r.queue_position, reg))) > 0\n+\n+\n def is_user_present(member, event):\n     if not event.registration_required or not member.is_authenticated:\n         return None\n", "issue": "Use a different colour for waiting list events\n### Is your feature request related to a problem? Please describe.\r\nIn the event overview calendar, the dot in front of the event is colored as if you are registered. And this is confusing.\r\n\r\n### Describe the solution you'd like\r\nUse a different colour for events you're on the waiting list for.\r\n\r\n### Motivation\r\nBetter user experience.\r\n\r\n### Describe alternatives you've considered\r\nThere is not really any alternative\r\n\r\n### Additional context\r\nCreated based on #1007\r\n\n", "before_files": [{"content": "from rest_framework.reverse import reverse\n\nfrom events import services\nfrom events.models import Event\nfrom thaliawebsite.api.calendarjs.serializers import CalenderJSSerializer\n\n\nclass EventsCalenderJSSerializer(CalenderJSSerializer):\n    class Meta(CalenderJSSerializer.Meta):\n        model = Event\n\n    def _url(self, instance):\n        return reverse(\"events:event\", kwargs={\"pk\": instance.id})\n\n    def _class_names(self, instance):\n        class_names = [\"regular-event\"]\n        if self.context[\"member\"] and services.is_user_registered(\n            self.context[\"member\"], instance\n        ):\n            class_names.append(\"has-registration\")\n        return class_names\n\n\nclass UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):\n    \"\"\"See CalenderJSSerializer, customised classes.\"\"\"\n\n    class Meta(CalenderJSSerializer.Meta):\n        model = Event\n\n    def _class_names(self, instance):\n        return [\"unpublished-event\"]\n\n    def _url(self, instance):\n        return reverse(\"admin:events_event_details\", kwargs={\"pk\": instance.id})\n", "path": "website/events/api/calendarjs/serializers.py"}, {"content": "from collections import OrderedDict\n\nfrom django.utils import timezone\nfrom django.utils.datetime_safe import date\nfrom django.utils.translation import gettext_lazy as _, get_language\n\nfrom events import emails\nfrom events.exceptions import RegistrationError\nfrom events.models import EventRegistration, RegistrationInformationField, Event\nfrom payments.api.v1.fields import PaymentTypeField\nfrom payments.services import create_payment, delete_payment\nfrom utils.snippets import datetime_to_lectureyear\n\n\ndef is_user_registered(member, event):\n    \"\"\"Return if the user is registered for the specified event.\n\n    :param member: the user\n    :param event: the event\n    :return: None if registration is not required or no member else True/False\n    \"\"\"\n    if not event.registration_required or not member.is_authenticated:\n        return None\n\n    return event.registrations.filter(member=member, date_cancelled=None).count() > 0\n\n\ndef is_user_present(member, event):\n    if not event.registration_required or not member.is_authenticated:\n        return None\n\n    return (\n        event.registrations.filter(\n            member=member, date_cancelled=None, present=True\n        ).count()\n        > 0\n    )\n\n\ndef event_permissions(member, event, name=None):\n    \"\"\"Return a dictionary with the available event permissions of the user.\n\n    :param member: the user\n    :param event: the event\n    :param name: the name of a non member registration\n    :return: the permission dictionary\n    \"\"\"\n    perms = {\n        \"create_registration\": False,\n        \"cancel_registration\": False,\n        \"update_registration\": False,\n        \"manage_event\": is_organiser(member, event),\n    }\n    if not member:\n        return perms\n    if not (member.is_authenticated or name):\n        return perms\n\n    registration = None\n    try:\n        registration = EventRegistration.objects.get(\n            event=event, member=member, name=name\n        )\n    except EventRegistration.DoesNotExist:\n        pass\n\n    perms[\"create_registration\"] = (\n        (registration is None or registration.date_cancelled is not None)\n        and (event.registration_allowed or not event.registration_required)\n        and (name or member.can_attend_events)\n    )\n    perms[\"cancel_registration\"] = (\n        registration is not None\n        and registration.date_cancelled is None\n        and (event.cancellation_allowed or name or not event.registration_required)\n        and registration.payment is None\n    )\n    perms[\"update_registration\"] = (\n        registration is not None\n        and registration.date_cancelled is None\n        and event.has_fields\n        and (event.registration_allowed or not event.registration_required)\n        and (name or member.can_attend_events)\n    )\n    return perms\n\n\ndef is_organiser(member, event):\n    if member and member.is_authenticated:\n        if member.is_superuser or member.has_perm(\"events.override_organiser\"):\n            return True\n\n        if event:\n            return member.get_member_groups().filter(pk=event.organiser.pk).count() != 0\n\n    return False\n\n\ndef create_registration(member, event):\n    \"\"\"Create a new user registration for an event.\n\n    :param member: the user\n    :param event: the event\n    :return: Return the registration if successful\n    \"\"\"\n    if event_permissions(member, event)[\"create_registration\"]:\n        registration = None\n        try:\n            registration = EventRegistration.objects.get(event=event, member=member)\n        except EventRegistration.DoesNotExist:\n            pass\n\n        if registration is None:\n            return EventRegistration.objects.create(event=event, member=member)\n        if registration.date_cancelled is not None:\n            if registration.is_late_cancellation():\n                raise RegistrationError(\n                    _(\n                        \"You cannot re-register anymore \"\n                        \"since you've cancelled after the \"\n                        \"deadline.\"\n                    )\n                )\n            registration.date = timezone.now()\n            registration.date_cancelled = None\n            registration.save()\n\n        return registration\n    if event_permissions(member, event)[\"cancel_registration\"]:\n        raise RegistrationError(_(\"You were already registered.\"))\n    raise RegistrationError(_(\"You may not register.\"))\n\n\ndef cancel_registration(member, event):\n    \"\"\"Cancel a user registration for an event.\n\n    :param member: the user\n    :param event: the event\n    \"\"\"\n    registration = None\n    try:\n        registration = EventRegistration.objects.get(event=event, member=member)\n    except EventRegistration.DoesNotExist:\n        pass\n\n    if event_permissions(member, event)[\"cancel_registration\"] and registration:\n        if not registration.queue_position:\n            emails.notify_first_waiting(event)\n\n            if event.send_cancel_email and event.after_cancel_deadline:\n                emails.notify_organiser(event, registration)\n\n        # Note that this doesn\"t remove the values for the\n        # information fields that the user entered upon registering.\n        # But this is regarded as a feature, not a bug. Especially\n        # since the values will still appear in the backend.\n        registration.date_cancelled = timezone.now()\n        registration.save()\n    else:\n        raise RegistrationError(_(\"You are not allowed to deregister for this event.\"))\n\n\ndef update_registration(\n    member=None, event=None, name=None, registration=None, field_values=None\n):\n    \"\"\"Update a user registration of an event.\n\n    :param request: http request\n    :param member: the user\n    :param event: the event\n    :param name: the name of a registration not associated with a user\n    :param registration: the registration\n    :param field_values: values for the information fields\n    \"\"\"\n    if not registration:\n        try:\n            registration = EventRegistration.objects.get(\n                event=event, member=member, name=name\n            )\n        except EventRegistration.DoesNotExist as error:\n            raise RegistrationError(\n                _(\"You are not registered for this event.\")\n            ) from error\n    else:\n        member = registration.member\n        event = registration.event\n        name = registration.name\n\n    if (\n        not event_permissions(member, event, name)[\"update_registration\"]\n        or not field_values\n    ):\n        return\n\n    for field_id, field_value in field_values:\n        field = RegistrationInformationField.objects.get(\n            id=field_id.replace(\"info_field_\", \"\")\n        )\n\n        if (\n            field.type == RegistrationInformationField.INTEGER_FIELD\n            and field_value is None\n        ):\n            field_value = 0\n        elif (\n            field.type == RegistrationInformationField.BOOLEAN_FIELD\n            and field_value is None\n        ):\n            field_value = False\n        elif (\n            field.type == RegistrationInformationField.TEXT_FIELD\n            and field_value is None\n        ):\n            field_value = \"\"\n\n        field.set_value_for(registration, field_value)\n\n\ndef registration_fields(request, member=None, event=None, registration=None, name=None):\n    \"\"\"Return information about the registration fields of a registration.\n\n    :param member: the user (optional if registration provided)\n    :param name: the name of a non member registration\n                 (optional if registration provided)\n    :param event: the event (optional if registration provided)\n    :param registration: the registration (optional if member & event provided)\n    :return: the fields\n    \"\"\"\n    if registration is None:\n        try:\n            registration = EventRegistration.objects.get(\n                event=event, member=member, name=name\n            )\n        except EventRegistration.DoesNotExist as error:\n            raise RegistrationError(\n                _(\"You are not registered for this event.\")\n            ) from error\n        except EventRegistration.MultipleObjectsReturned as error:\n            raise RegistrationError(\n                _(\"Unable to find the right registration.\")\n            ) from error\n\n    member = registration.member\n    event = registration.event\n    name = registration.name\n\n    perms = event_permissions(member, event, name)[\n        \"update_registration\"\n    ] or is_organiser(request.member, event)\n    if perms and registration:\n        information_fields = registration.information_fields\n        fields = OrderedDict()\n\n        for information_field in information_fields:\n            field = information_field[\"field\"]\n\n            fields[\"info_field_{}\".format(field.id)] = {\n                \"type\": field.type,\n                \"label\": getattr(field, \"{}_{}\".format(\"name\", get_language())),\n                \"description\": getattr(\n                    field, \"{}_{}\".format(\"description\", get_language())\n                ),\n                \"value\": information_field[\"value\"],\n                \"required\": field.required,\n            }\n\n        return fields\n    raise RegistrationError(_(\"You are not allowed to update this registration.\"))\n\n\ndef update_registration_by_organiser(registration, member, data):\n    if not is_organiser(member, registration.event):\n        raise RegistrationError(_(\"You are not allowed to update this registration.\"))\n\n    if \"payment\" in data:\n        if data[\"payment\"][\"type\"] == PaymentTypeField.NO_PAYMENT:\n            if registration.payment is not None:\n                delete_payment(registration)\n        else:\n            registration.payment = create_payment(\n                payable=registration,\n                processed_by=member,\n                pay_type=data[\"payment\"][\"type\"],\n            )\n\n    if \"present\" in data:\n        registration.present = data[\"present\"]\n\n    registration.save()\n\n\ndef generate_category_statistics():\n    \"\"\"Generate statistics about events, number of events per category.\n\n    :return: Dict with key, value resp. being category, event count.\n    \"\"\"\n    year = datetime_to_lectureyear(timezone.now())\n\n    data = {}\n    for i in range(5):\n        year_start = date(year=year - i, month=9, day=1)\n        year_end = date(year=year - i + 1, month=9, day=1)\n        data[str(year - i)] = {\n            str(display): Event.objects.filter(\n                category=key, start__gte=year_start, end__lte=year_end\n            ).count()\n            for key, display in Event.EVENT_CATEGORIES\n        }\n\n    return data\n", "path": "website/events/services.py"}], "after_files": [{"content": "from rest_framework.reverse import reverse\n\nfrom events import services\nfrom events.models import Event\nfrom thaliawebsite.api.calendarjs.serializers import CalenderJSSerializer\n\n\nclass EventsCalenderJSSerializer(CalenderJSSerializer):\n    class Meta(CalenderJSSerializer.Meta):\n        model = Event\n\n    def _url(self, instance):\n        return reverse(\"events:event\", kwargs={\"pk\": instance.id})\n\n    def _class_names(self, instance):\n        if self.context[\"member\"] and services.is_user_registered(\n            self.context[\"member\"], instance\n        ):\n            if services.user_registration_pending(self.context[\"member\"], instance):\n                return [\"regular-event-pending-registration\"]\n            else:\n                return [\"regular-event-has-registration\"]\n        elif (not instance.registration_required) or instance.registration_allowed:\n            return [\"regular-event-registration-open\"]\n        else:\n            # I think this handles the case that registration is needed, but not yet possible\n            return [\"regular-event-registration-closed\"]\n\n\nclass UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):\n    \"\"\"See CalenderJSSerializer, customised classes.\"\"\"\n\n    class Meta(CalenderJSSerializer.Meta):\n        model = Event\n\n    def _class_names(self, instance):\n        return [\"unpublished-event\"]\n\n    def _url(self, instance):\n        return reverse(\"admin:events_event_details\", kwargs={\"pk\": instance.id})\n", "path": "website/events/api/calendarjs/serializers.py"}, {"content": "from collections import OrderedDict\n\nfrom django.utils import timezone\nfrom django.utils.datetime_safe import date\nfrom django.utils.translation import gettext_lazy as _, get_language\n\nfrom events import emails\nfrom events.exceptions import RegistrationError\nfrom events.models import EventRegistration, RegistrationInformationField, Event\nfrom payments.api.v1.fields import PaymentTypeField\nfrom payments.services import create_payment, delete_payment\nfrom utils.snippets import datetime_to_lectureyear\n\n\ndef is_user_registered(member, event):\n    \"\"\"Return if the user is registered for the specified event.\n\n    :param member: the user\n    :param event: the event\n    :return: None if registration is not required or no member else True/False\n    \"\"\"\n    if not member.is_authenticated:\n        return None\n\n    return event.registrations.filter(member=member, date_cancelled=None).count() > 0\n\n\ndef user_registration_pending(member, event):\n    \"\"\"Return if the user is in the queue, but not yet registered for, the specific event.\n\n    :param member: the user\n    :param event: the event\n    :return: None if registration is not required or no member else True/False\n    \"\"\"\n    if not event.registration_required:\n        return False\n    if not member.is_authenticated:\n        return None\n\n    reg = event.registrations.filter(member=member, date_cancelled=None)\n    return len(list(filter(lambda r: r.queue_position, reg))) > 0\n\n\ndef is_user_present(member, event):\n    if not event.registration_required or not member.is_authenticated:\n        return None\n\n    return (\n        event.registrations.filter(\n            member=member, date_cancelled=None, present=True\n        ).count()\n        > 0\n    )\n\n\ndef event_permissions(member, event, name=None):\n    \"\"\"Return a dictionary with the available event permissions of the user.\n\n    :param member: the user\n    :param event: the event\n    :param name: the name of a non member registration\n    :return: the permission dictionary\n    \"\"\"\n    perms = {\n        \"create_registration\": False,\n        \"cancel_registration\": False,\n        \"update_registration\": False,\n        \"manage_event\": is_organiser(member, event),\n    }\n    if not member:\n        return perms\n    if not (member.is_authenticated or name):\n        return perms\n\n    registration = None\n    try:\n        registration = EventRegistration.objects.get(\n            event=event, member=member, name=name\n        )\n    except EventRegistration.DoesNotExist:\n        pass\n\n    perms[\"create_registration\"] = (\n        (registration is None or registration.date_cancelled is not None)\n        and (event.registration_allowed or not event.registration_required)\n        and (name or member.can_attend_events)\n    )\n    perms[\"cancel_registration\"] = (\n        registration is not None\n        and registration.date_cancelled is None\n        and (event.cancellation_allowed or name or not event.registration_required)\n        and registration.payment is None\n    )\n    perms[\"update_registration\"] = (\n        registration is not None\n        and registration.date_cancelled is None\n        and event.has_fields\n        and (event.registration_allowed or not event.registration_required)\n        and (name or member.can_attend_events)\n    )\n    return perms\n\n\ndef is_organiser(member, event):\n    if member and member.is_authenticated:\n        if member.is_superuser or member.has_perm(\"events.override_organiser\"):\n            return True\n\n        if event:\n            return member.get_member_groups().filter(pk=event.organiser.pk).count() != 0\n\n    return False\n\n\ndef create_registration(member, event):\n    \"\"\"Create a new user registration for an event.\n\n    :param member: the user\n    :param event: the event\n    :return: Return the registration if successful\n    \"\"\"\n    if event_permissions(member, event)[\"create_registration\"]:\n        registration = None\n        try:\n            registration = EventRegistration.objects.get(event=event, member=member)\n        except EventRegistration.DoesNotExist:\n            pass\n\n        if registration is None:\n            return EventRegistration.objects.create(event=event, member=member)\n        if registration.date_cancelled is not None:\n            if registration.is_late_cancellation():\n                raise RegistrationError(\n                    _(\n                        \"You cannot re-register anymore \"\n                        \"since you've cancelled after the \"\n                        \"deadline.\"\n                    )\n                )\n            registration.date = timezone.now()\n            registration.date_cancelled = None\n            registration.save()\n\n        return registration\n    if event_permissions(member, event)[\"cancel_registration\"]:\n        raise RegistrationError(_(\"You were already registered.\"))\n    raise RegistrationError(_(\"You may not register.\"))\n\n\ndef cancel_registration(member, event):\n    \"\"\"Cancel a user registration for an event.\n\n    :param member: the user\n    :param event: the event\n    \"\"\"\n    registration = None\n    try:\n        registration = EventRegistration.objects.get(event=event, member=member)\n    except EventRegistration.DoesNotExist:\n        pass\n\n    if event_permissions(member, event)[\"cancel_registration\"] and registration:\n        if not registration.queue_position:\n            emails.notify_first_waiting(event)\n\n            if event.send_cancel_email and event.after_cancel_deadline:\n                emails.notify_organiser(event, registration)\n\n        # Note that this doesn\"t remove the values for the\n        # information fields that the user entered upon registering.\n        # But this is regarded as a feature, not a bug. Especially\n        # since the values will still appear in the backend.\n        registration.date_cancelled = timezone.now()\n        registration.save()\n    else:\n        raise RegistrationError(_(\"You are not allowed to deregister for this event.\"))\n\n\ndef update_registration(\n    member=None, event=None, name=None, registration=None, field_values=None\n):\n    \"\"\"Update a user registration of an event.\n\n    :param request: http request\n    :param member: the user\n    :param event: the event\n    :param name: the name of a registration not associated with a user\n    :param registration: the registration\n    :param field_values: values for the information fields\n    \"\"\"\n    if not registration:\n        try:\n            registration = EventRegistration.objects.get(\n                event=event, member=member, name=name\n            )\n        except EventRegistration.DoesNotExist as error:\n            raise RegistrationError(\n                _(\"You are not registered for this event.\")\n            ) from error\n    else:\n        member = registration.member\n        event = registration.event\n        name = registration.name\n\n    if (\n        not event_permissions(member, event, name)[\"update_registration\"]\n        or not field_values\n    ):\n        return\n\n    for field_id, field_value in field_values:\n        field = RegistrationInformationField.objects.get(\n            id=field_id.replace(\"info_field_\", \"\")\n        )\n\n        if (\n            field.type == RegistrationInformationField.INTEGER_FIELD\n            and field_value is None\n        ):\n            field_value = 0\n        elif (\n            field.type == RegistrationInformationField.BOOLEAN_FIELD\n            and field_value is None\n        ):\n            field_value = False\n        elif (\n            field.type == RegistrationInformationField.TEXT_FIELD\n            and field_value is None\n        ):\n            field_value = \"\"\n\n        field.set_value_for(registration, field_value)\n\n\ndef registration_fields(request, member=None, event=None, registration=None, name=None):\n    \"\"\"Return information about the registration fields of a registration.\n\n    :param member: the user (optional if registration provided)\n    :param name: the name of a non member registration\n                 (optional if registration provided)\n    :param event: the event (optional if registration provided)\n    :param registration: the registration (optional if member & event provided)\n    :return: the fields\n    \"\"\"\n    if registration is None:\n        try:\n            registration = EventRegistration.objects.get(\n                event=event, member=member, name=name\n            )\n        except EventRegistration.DoesNotExist as error:\n            raise RegistrationError(\n                _(\"You are not registered for this event.\")\n            ) from error\n        except EventRegistration.MultipleObjectsReturned as error:\n            raise RegistrationError(\n                _(\"Unable to find the right registration.\")\n            ) from error\n\n    member = registration.member\n    event = registration.event\n    name = registration.name\n\n    perms = event_permissions(member, event, name)[\n        \"update_registration\"\n    ] or is_organiser(request.member, event)\n    if perms and registration:\n        information_fields = registration.information_fields\n        fields = OrderedDict()\n\n        for information_field in information_fields:\n            field = information_field[\"field\"]\n\n            fields[\"info_field_{}\".format(field.id)] = {\n                \"type\": field.type,\n                \"label\": getattr(field, \"{}_{}\".format(\"name\", get_language())),\n                \"description\": getattr(\n                    field, \"{}_{}\".format(\"description\", get_language())\n                ),\n                \"value\": information_field[\"value\"],\n                \"required\": field.required,\n            }\n\n        return fields\n    raise RegistrationError(_(\"You are not allowed to update this registration.\"))\n\n\ndef update_registration_by_organiser(registration, member, data):\n    if not is_organiser(member, registration.event):\n        raise RegistrationError(_(\"You are not allowed to update this registration.\"))\n\n    if \"payment\" in data:\n        if data[\"payment\"][\"type\"] == PaymentTypeField.NO_PAYMENT:\n            if registration.payment is not None:\n                delete_payment(registration)\n        else:\n            registration.payment = create_payment(\n                payable=registration,\n                processed_by=member,\n                pay_type=data[\"payment\"][\"type\"],\n            )\n\n    if \"present\" in data:\n        registration.present = data[\"present\"]\n\n    registration.save()\n\n\ndef generate_category_statistics():\n    \"\"\"Generate statistics about events, number of events per category.\n\n    :return: Dict with key, value resp. being category, event count.\n    \"\"\"\n    year = datetime_to_lectureyear(timezone.now())\n\n    data = {}\n    for i in range(5):\n        year_start = date(year=year - i, month=9, day=1)\n        year_end = date(year=year - i + 1, month=9, day=1)\n        data[str(year - i)] = {\n            str(display): Event.objects.filter(\n                category=key, start__gte=year_start, end__lte=year_end\n            ).count()\n            for key, display in Event.EVENT_CATEGORIES\n        }\n\n    return data\n", "path": "website/events/services.py"}]}