We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Events presence registration in app creates payment
### Describe the bug

Events presence registration in app creates payment

### How to reproduce
Steps to reproduce the behaviour:
1. Create an event with registrations
2. Register
3. Mark the registration as present _in the app_
You can simulate this by going to the registration using the API on `/v1/api/registrations/` and patching the body:
```
{
    "payment": "no_payment",
    "present": true
}
```
4. Note that a payment with the status 'no payment' is created for this registration

### Expected behaviour

No payment should be created



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

{"golden_diff": "diff --git a/website/events/services.py b/website/events/services.py\n--- a/website/events/services.py\n+++ b/website/events/services.py\n@@ -293,11 +293,9 @@\n         raise RegistrationError(_(\"You are not allowed to update this registration.\"))\n \n     if \"payment\" in data:\n-        if (\n-            data[\"payment\"][\"type\"] == PaymentTypeField.NO_PAYMENT\n-            and registration.payment is not None\n-        ):\n-            delete_payment(registration)\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", "issue": "Events presence registration in app creates payment\n### Describe the bug\r\n\r\nEvents presence registration in app creates payment\r\n\r\n### How to reproduce\r\nSteps to reproduce the behaviour:\r\n1. Create an event with registrations\r\n2. Register\r\n3. Mark the registration as present _in the app_\r\nYou can simulate this by going to the registration using the API on `/v1/api/registrations/` and patching the body:\r\n```\r\n{\r\n    \"payment\": \"no_payment\",\r\n    \"present\": true\r\n}\r\n```\r\n4. Note that a payment with the status 'no payment' is created for this registration\r\n\r\n### Expected behaviour\r\n\r\nNo payment should be created\r\n\r\n\n", "before_files": [{"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.fields import PaymentTypeField\nfrom payments.models import Payment\nfrom payments.services import create_payment, delete_payment\nfrom utils.snippets import datetime_to_lectureyear\n\n\ndef is_user_registered(member, event):\n    \"\"\"\n    Returns 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 event_permissions(member, event, name=None):\n    \"\"\"\n    Returns 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    }\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\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)\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\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    \"\"\"\n    Creates a new user registration for an event\n\n    :param member: the user\n    :param event: the event\n    :return: returns 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        elif 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            else:\n                registration.date = timezone.now()\n                registration.date_cancelled = None\n                registration.save()\n\n        return registration\n    elif event_permissions(member, event)[\"cancel_registration\"]:\n        raise RegistrationError(_(\"You were already registered.\"))\n    else:\n        raise RegistrationError(_(\"You may not register.\"))\n\n\ndef cancel_registration(member, event):\n    \"\"\"\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 registration.payment is not None:\n            delete_payment(registration)\n        if registration.queue_position == 0:\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 registered for this event.\"))\n\n\ndef pay_with_tpay(member, event):\n    \"\"\"\n    Add a Thalia Pay payment to an event registration\n\n    :param member: the user\n    :param event: the event\n    \"\"\"\n    try:\n        registration = EventRegistration.objects.get(event=event, member=member)\n    except EventRegistration.DoesNotExist:\n        raise RegistrationError(_(\"You are not registered for this event.\"))\n\n    if registration.payment is None:\n        registration.payment = create_payment(\n            payable=registration, processed_by=member, pay_type=Payment.TPAY\n        )\n        registration.save()\n    else:\n        raise RegistrationError(_(\"You have already paid for this event.\"))\n\n\ndef update_registration(\n    member=None, event=None, name=None, registration=None, field_values=None\n):\n    \"\"\"\n    Updates 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    \"\"\"\n    Returns 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\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    else:\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    else:\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 (\n            data[\"payment\"][\"type\"] == PaymentTypeField.NO_PAYMENT\n            and registration.payment is not None\n        ):\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    \"\"\"\n    Generate statistics about events, number of events per category\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 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.fields import PaymentTypeField\nfrom payments.models import Payment\nfrom payments.services import create_payment, delete_payment\nfrom utils.snippets import datetime_to_lectureyear\n\n\ndef is_user_registered(member, event):\n    \"\"\"\n    Returns 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 event_permissions(member, event, name=None):\n    \"\"\"\n    Returns 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    }\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\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)\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\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    \"\"\"\n    Creates a new user registration for an event\n\n    :param member: the user\n    :param event: the event\n    :return: returns 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        elif 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            else:\n                registration.date = timezone.now()\n                registration.date_cancelled = None\n                registration.save()\n\n        return registration\n    elif event_permissions(member, event)[\"cancel_registration\"]:\n        raise RegistrationError(_(\"You were already registered.\"))\n    else:\n        raise RegistrationError(_(\"You may not register.\"))\n\n\ndef cancel_registration(member, event):\n    \"\"\"\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 registration.payment is not None:\n            delete_payment(registration)\n        if registration.queue_position == 0:\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 registered for this event.\"))\n\n\ndef pay_with_tpay(member, event):\n    \"\"\"\n    Add a Thalia Pay payment to an event registration\n\n    :param member: the user\n    :param event: the event\n    \"\"\"\n    try:\n        registration = EventRegistration.objects.get(event=event, member=member)\n    except EventRegistration.DoesNotExist:\n        raise RegistrationError(_(\"You are not registered for this event.\"))\n\n    if registration.payment is None:\n        registration.payment = create_payment(\n            payable=registration, processed_by=member, pay_type=Payment.TPAY\n        )\n        registration.save()\n    else:\n        raise RegistrationError(_(\"You have already paid for this event.\"))\n\n\ndef update_registration(\n    member=None, event=None, name=None, registration=None, field_values=None\n):\n    \"\"\"\n    Updates 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    \"\"\"\n    Returns 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\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    else:\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    else:\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    \"\"\"\n    Generate statistics about events, number of events per category\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"}]}