We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Ordering food for an event you are not registered for
### Describe the bug
<!-- A clear and concise description of what the bug is. -->
You can order food for an event you are not registered for. I was not registered for the 'Spring Beach Party' but I could order food.

### Expected behaviour
<!-- A clear and concise description of what you expected to happen. -->
I expect you can only order food for an event you are registered for or an event where registration is not necessary.



--- 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/pizzas/api/v2/views.py`
Content:
```
1 from django.db.models import Prefetch
2 
3 from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
4 from rest_framework import filters as framework_filters
5 from rest_framework import status
6 from rest_framework.generics import (
7     CreateAPIView,
8     DestroyAPIView,
9     ListAPIView,
10     RetrieveAPIView,
11     UpdateAPIView,
12     get_object_or_404,
13 )
14 from rest_framework.response import Response
15 
16 from events.models.event_registration import EventRegistration
17 from payments.exceptions import PaymentError
18 from payments.services import delete_payment
19 from pizzas.api.v2 import filters
20 from pizzas.api.v2.serializers import (
21     FoodOrderCreateSerializer,
22     FoodOrderSerializer,
23     FoodOrderUpdateSerializer,
24     ProductSerializer,
25 )
26 from pizzas.api.v2.serializers.food_event import FoodEventSerializer
27 from pizzas.models import FoodEvent, FoodOrder, Product
28 from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod
29 
30 
31 class FoodEventListView(ListAPIView):
32     """Returns an overview of all food events."""
33 
34     serializer_class = FoodEventSerializer
35     filter_backends = (
36         framework_filters.OrderingFilter,
37         filters.FoodEventDateFilterBackend,
38     )
39     ordering_fields = ("start", "end")
40     permission_classes = [
41         IsAuthenticatedOrTokenHasScope,
42     ]
43     required_scopes = ["food:read"]
44 
45     def get_queryset(self):
46         events = FoodEvent.objects.all()
47         if self.request.member:
48             events = events.prefetch_related(
49                 Prefetch(
50                     "event__eventregistration_set",
51                     to_attr="member_registration",
52                     queryset=EventRegistration.objects.filter(
53                         member=self.request.member
54                     ).select_properties("queue_position"),
55                 )
56             )
57         return events
58 
59 
60 class FoodEventDetailView(RetrieveAPIView):
61     """Returns one single food event."""
62 
63     serializer_class = FoodEventSerializer
64     permission_classes = [
65         IsAuthenticatedOrTokenHasScope,
66     ]
67     required_scopes = ["food:read"]
68 
69     def get_queryset(self):
70         events = FoodEvent.objects.all()
71         if self.request.member:
72             events = events.prefetch_related(
73                 Prefetch(
74                     "event__eventregistration_set",
75                     to_attr="member_registration",
76                     queryset=EventRegistration.objects.filter(
77                         member=self.request.member
78                     ).select_properties("queue_position"),
79                 )
80             )
81         return events
82 
83 
84 class FoodEventProductsListView(ListAPIView):
85     """Returns an overview of all products."""
86 
87     serializer_class = ProductSerializer
88     queryset = Product.available_products.all()
89     filter_backends = (framework_filters.SearchFilter,)
90     search_fields = ("name",)
91     permission_classes = [
92         IsAuthenticatedOrTokenHasScope,
93     ]
94     required_scopes = ["food:read"]
95 
96 
97 class FoodEventOrderDetailView(
98     RetrieveAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView
99 ):
100     """Returns details of a food order."""
101 
102     permission_classes = [
103         IsAuthenticatedOrTokenHasScopeForMethod,
104     ]
105     required_scopes_per_method = {
106         "GET": ["food:read"],
107         "POST": ["food:order"],
108         "PUT": ["food:order"],
109         "PATCH": ["food:order"],
110         "DELETE": ["food:order"],
111     }
112 
113     def get_serializer_class(self):
114         if self.request.method.lower() == "get":
115             return FoodOrderSerializer
116         if self.request.method.lower() == "post":
117             return FoodOrderCreateSerializer
118         return FoodOrderUpdateSerializer
119 
120     def get_queryset(self):
121         return FoodOrder.objects.filter(food_event=self.food_event)
122 
123     def get_object(self):
124         queryset = self.filter_queryset(self.get_queryset())
125         obj = get_object_or_404(queryset, member=self.request.member)
126 
127         # May raise a permission denied
128         self.check_object_permissions(self.request, obj)
129 
130         return obj
131 
132     def dispatch(self, request, *args, **kwargs):
133         self.food_event = get_object_or_404(FoodEvent, pk=self.kwargs.get("pk"))
134         try:
135             return super().dispatch(request, *args, **kwargs)
136         except PaymentError as e:
137             return Response(
138                 str(e),
139                 status=status.HTTP_403_FORBIDDEN,
140             )
141 
142     def update(self, request, *args, **kwargs):
143         instance = self.get_object()
144 
145         if instance.payment:
146             delete_payment(instance, member=request.member, ignore_change_window=True)
147 
148         super().update(request, *args, **kwargs)
149 
150         return Response(
151             FoodOrderSerializer(instance, context=self.get_serializer_context()).data
152         )
153 
154     def create(self, request, *args, **kwargs):
155         serializer = self.get_serializer(data=request.data)
156         serializer.is_valid(raise_exception=True)
157         self.perform_create(serializer)
158         return Response(
159             FoodOrderSerializer(
160                 serializer.instance, context=self.get_serializer_context()
161             ).data,
162             status=status.HTTP_201_CREATED,
163         )
164
```

Path: `website/pizzas/views.py`
Content:
```
1 """Views provided by the pizzas package."""
2 from django.contrib import messages
3 from django.contrib.auth.decorators import login_required
4 from django.http import Http404
5 from django.shortcuts import get_object_or_404, redirect, render
6 from django.utils.translation import gettext_lazy as _
7 from django.views.decorators.http import require_http_methods
8 
9 from payments.exceptions import PaymentError
10 from payments.services import delete_payment
11 
12 from .models import FoodEvent, FoodOrder, Product
13 
14 
15 @login_required
16 def index(request):
17     """Overview of user order for a pizza event."""
18     products = Product.available_products.order_by("name")
19     if not request.user.has_perm("pizzas.order_restricted_products"):
20         products = products.exclude(restricted=True)
21     event = FoodEvent.current()
22     try:
23         obj = FoodOrder.objects.get(food_event=event, member=request.member)
24     except FoodOrder.DoesNotExist:
25         obj = None
26     context = {"event": event, "products": products, "order": obj}
27     return render(request, "pizzas/index.html", context)
28 
29 
30 @require_http_methods(["POST"])
31 def cancel_order(request):
32     """View that cancels a user's order."""
33     if "order" in request.POST:
34         try:
35             order = get_object_or_404(FoodOrder, pk=int(request.POST["order"]))
36             if not order.can_be_changed:
37                 messages.error(request, _("You can no longer cancel."))
38             elif order.member == request.member:
39                 try:
40                     order.delete()
41                     messages.success(request, _("Your order has been cancelled."))
42                 except PaymentError as e:
43                     messages.error(request, str(e))
44         except Http404:
45             messages.error(request, _("Your order could not be found."))
46     return redirect("pizzas:index")
47 
48 
49 @login_required
50 def place_order(request):
51     """View that shows the detail of the current order."""
52     event = FoodEvent.current()
53     if not event:
54         return redirect("pizzas:index")
55 
56     try:
57         obj = FoodOrder.objects.get(food_event=event, member=request.member)
58         current_order_locked = not obj.can_be_changed
59     except FoodOrder.DoesNotExist:
60         obj = None
61         current_order_locked = False
62 
63     if "product" in request.POST and not current_order_locked:
64         productset = Product.available_products.all()
65         if not request.user.has_perm("pizzas.order_restricted_products"):
66             productset = productset.exclude(restricted=True)
67         try:
68             product = productset.get(pk=int(request.POST["product"]))
69         except Product.DoesNotExist as e:
70             raise Http404("Pizza does not exist") from e
71         if not obj:
72             obj = FoodOrder(food_event=event, member=request.member)
73         obj.product = product
74         if obj.payment:
75             try:
76                 delete_payment(obj, member=request.member, ignore_change_window=True)
77             except PaymentError:
78                 messages.error(
79                     request,
80                     _("Your order could not be updated because it was already paid."),
81                 )
82                 return redirect("pizzas:index")
83         obj.save()
84     return redirect("pizzas:index")
85
```
--- 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/pizzas/api/v2/views.py b/website/pizzas/api/v2/views.py
--- a/website/pizzas/api/v2/views.py
+++ b/website/pizzas/api/v2/views.py
@@ -1,8 +1,10 @@
 from django.db.models import Prefetch
+from django.utils import timezone
 
 from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
 from rest_framework import filters as framework_filters
 from rest_framework import status
+from rest_framework.exceptions import PermissionDenied
 from rest_framework.generics import (
     CreateAPIView,
     DestroyAPIView,
@@ -141,7 +143,8 @@
 
     def update(self, request, *args, **kwargs):
         instance = self.get_object()
-
+        if instance.event.has_ended:
+            raise PermissionDenied
         if instance.payment:
             delete_payment(instance, member=request.member, ignore_change_window=True)
 
@@ -152,6 +155,19 @@
         )
 
     def create(self, request, *args, **kwargs):
+        if self.food_event.start > timezone.now():
+            raise PermissionDenied("You cannot order food yet")
+        if self.food_event.has_ended:
+            raise PermissionDenied("Event has ended")
+
+        event = self.food_event.event
+        if event.registration_required:
+            registration = event.registrations.filter(
+                member=request.member, date_cancelled=None
+            ).first()
+            if registration is None or not registration.is_invited:
+                raise PermissionDenied("You are not registered for this event")
+
         serializer = self.get_serializer(data=request.data)
         serializer.is_valid(raise_exception=True)
         self.perform_create(serializer)
diff --git a/website/pizzas/views.py b/website/pizzas/views.py
--- a/website/pizzas/views.py
+++ b/website/pizzas/views.py
@@ -3,6 +3,7 @@
 from django.contrib.auth.decorators import login_required
 from django.http import Http404
 from django.shortcuts import get_object_or_404, redirect, render
+from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from django.views.decorators.http import require_http_methods
 
@@ -23,7 +24,27 @@
         obj = FoodOrder.objects.get(food_event=event, member=request.member)
     except FoodOrder.DoesNotExist:
         obj = None
-    context = {"event": event, "products": products, "order": obj}
+
+    registrated_required = (
+        event is not None
+        and event.event is not None
+        and event.event.registration_required
+    )
+    not_registered = False
+    if registrated_required:
+        registration = event.event.registrations.filter(
+            member=request.member, date_cancelled=None
+        ).first()
+
+        if registration is None or not registration.is_invited:
+            not_registered = True
+
+    context = {
+        "event": event,
+        "products": products,
+        "order": obj,
+        "not_registered": not_registered,
+    }
     return render(request, "pizzas/index.html", context)
 
 
@@ -50,9 +71,23 @@
 def place_order(request):
     """View that shows the detail of the current order."""
     event = FoodEvent.current()
+
     if not event:
         return redirect("pizzas:index")
 
+    if event.start > timezone.now():
+        return redirect("pizzas:index")
+
+    if event.has_ended:
+        return redirect("pizzas:index")
+
+    if event.event.registration_required:
+        registration = event.event.registrations.filter(
+            member=request.member, date_cancelled=None
+        ).first()
+        if registration is None or not registration.is_invited:
+            return redirect("pizzas:index")
+
     try:
         obj = FoodOrder.objects.get(food_event=event, member=request.member)
         current_order_locked = not obj.can_be_changed

{"golden_diff": "diff --git a/website/pizzas/api/v2/views.py b/website/pizzas/api/v2/views.py\n--- a/website/pizzas/api/v2/views.py\n+++ b/website/pizzas/api/v2/views.py\n@@ -1,8 +1,10 @@\n from django.db.models import Prefetch\n+from django.utils import timezone\n \n from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope\n from rest_framework import filters as framework_filters\n from rest_framework import status\n+from rest_framework.exceptions import PermissionDenied\n from rest_framework.generics import (\n     CreateAPIView,\n     DestroyAPIView,\n@@ -141,7 +143,8 @@\n \n     def update(self, request, *args, **kwargs):\n         instance = self.get_object()\n-\n+        if instance.event.has_ended:\n+            raise PermissionDenied\n         if instance.payment:\n             delete_payment(instance, member=request.member, ignore_change_window=True)\n \n@@ -152,6 +155,19 @@\n         )\n \n     def create(self, request, *args, **kwargs):\n+        if self.food_event.start > timezone.now():\n+            raise PermissionDenied(\"You cannot order food yet\")\n+        if self.food_event.has_ended:\n+            raise PermissionDenied(\"Event has ended\")\n+\n+        event = self.food_event.event\n+        if event.registration_required:\n+            registration = event.registrations.filter(\n+                member=request.member, date_cancelled=None\n+            ).first()\n+            if registration is None or not registration.is_invited:\n+                raise PermissionDenied(\"You are not registered for this event\")\n+\n         serializer = self.get_serializer(data=request.data)\n         serializer.is_valid(raise_exception=True)\n         self.perform_create(serializer)\ndiff --git a/website/pizzas/views.py b/website/pizzas/views.py\n--- a/website/pizzas/views.py\n+++ b/website/pizzas/views.py\n@@ -3,6 +3,7 @@\n from django.contrib.auth.decorators import login_required\n from django.http import Http404\n from django.shortcuts import get_object_or_404, redirect, render\n+from django.utils import timezone\n from django.utils.translation import gettext_lazy as _\n from django.views.decorators.http import require_http_methods\n \n@@ -23,7 +24,27 @@\n         obj = FoodOrder.objects.get(food_event=event, member=request.member)\n     except FoodOrder.DoesNotExist:\n         obj = None\n-    context = {\"event\": event, \"products\": products, \"order\": obj}\n+\n+    registrated_required = (\n+        event is not None\n+        and event.event is not None\n+        and event.event.registration_required\n+    )\n+    not_registered = False\n+    if registrated_required:\n+        registration = event.event.registrations.filter(\n+            member=request.member, date_cancelled=None\n+        ).first()\n+\n+        if registration is None or not registration.is_invited:\n+            not_registered = True\n+\n+    context = {\n+        \"event\": event,\n+        \"products\": products,\n+        \"order\": obj,\n+        \"not_registered\": not_registered,\n+    }\n     return render(request, \"pizzas/index.html\", context)\n \n \n@@ -50,9 +71,23 @@\n def place_order(request):\n     \"\"\"View that shows the detail of the current order.\"\"\"\n     event = FoodEvent.current()\n+\n     if not event:\n         return redirect(\"pizzas:index\")\n \n+    if event.start > timezone.now():\n+        return redirect(\"pizzas:index\")\n+\n+    if event.has_ended:\n+        return redirect(\"pizzas:index\")\n+\n+    if event.event.registration_required:\n+        registration = event.event.registrations.filter(\n+            member=request.member, date_cancelled=None\n+        ).first()\n+        if registration is None or not registration.is_invited:\n+            return redirect(\"pizzas:index\")\n+\n     try:\n         obj = FoodOrder.objects.get(food_event=event, member=request.member)\n         current_order_locked = not obj.can_be_changed\n", "issue": "Ordering food for an event you are not registered for\n### Describe the bug\r\n<!-- A clear and concise description of what the bug is. -->\r\nYou can order food for an event you are not registered for. I was not registered for the 'Spring Beach Party' but I could order food.\r\n\r\n### Expected behaviour\r\n<!-- A clear and concise description of what you expected to happen. -->\r\nI expect you can only order food for an event you are registered for or an event where registration is not necessary.\r\n\r\n\n", "before_files": [{"content": "from django.db.models import Prefetch\n\nfrom oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope\nfrom rest_framework import filters as framework_filters\nfrom rest_framework import status\nfrom rest_framework.generics import (\n    CreateAPIView,\n    DestroyAPIView,\n    ListAPIView,\n    RetrieveAPIView,\n    UpdateAPIView,\n    get_object_or_404,\n)\nfrom rest_framework.response import Response\n\nfrom events.models.event_registration import EventRegistration\nfrom payments.exceptions import PaymentError\nfrom payments.services import delete_payment\nfrom pizzas.api.v2 import filters\nfrom pizzas.api.v2.serializers import (\n    FoodOrderCreateSerializer,\n    FoodOrderSerializer,\n    FoodOrderUpdateSerializer,\n    ProductSerializer,\n)\nfrom pizzas.api.v2.serializers.food_event import FoodEventSerializer\nfrom pizzas.models import FoodEvent, FoodOrder, Product\nfrom thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod\n\n\nclass FoodEventListView(ListAPIView):\n    \"\"\"Returns an overview of all food events.\"\"\"\n\n    serializer_class = FoodEventSerializer\n    filter_backends = (\n        framework_filters.OrderingFilter,\n        filters.FoodEventDateFilterBackend,\n    )\n    ordering_fields = (\"start\", \"end\")\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n    def get_queryset(self):\n        events = FoodEvent.objects.all()\n        if self.request.member:\n            events = events.prefetch_related(\n                Prefetch(\n                    \"event__eventregistration_set\",\n                    to_attr=\"member_registration\",\n                    queryset=EventRegistration.objects.filter(\n                        member=self.request.member\n                    ).select_properties(\"queue_position\"),\n                )\n            )\n        return events\n\n\nclass FoodEventDetailView(RetrieveAPIView):\n    \"\"\"Returns one single food event.\"\"\"\n\n    serializer_class = FoodEventSerializer\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n    def get_queryset(self):\n        events = FoodEvent.objects.all()\n        if self.request.member:\n            events = events.prefetch_related(\n                Prefetch(\n                    \"event__eventregistration_set\",\n                    to_attr=\"member_registration\",\n                    queryset=EventRegistration.objects.filter(\n                        member=self.request.member\n                    ).select_properties(\"queue_position\"),\n                )\n            )\n        return events\n\n\nclass FoodEventProductsListView(ListAPIView):\n    \"\"\"Returns an overview of all products.\"\"\"\n\n    serializer_class = ProductSerializer\n    queryset = Product.available_products.all()\n    filter_backends = (framework_filters.SearchFilter,)\n    search_fields = (\"name\",)\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n\nclass FoodEventOrderDetailView(\n    RetrieveAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView\n):\n    \"\"\"Returns details of a food order.\"\"\"\n\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScopeForMethod,\n    ]\n    required_scopes_per_method = {\n        \"GET\": [\"food:read\"],\n        \"POST\": [\"food:order\"],\n        \"PUT\": [\"food:order\"],\n        \"PATCH\": [\"food:order\"],\n        \"DELETE\": [\"food:order\"],\n    }\n\n    def get_serializer_class(self):\n        if self.request.method.lower() == \"get\":\n            return FoodOrderSerializer\n        if self.request.method.lower() == \"post\":\n            return FoodOrderCreateSerializer\n        return FoodOrderUpdateSerializer\n\n    def get_queryset(self):\n        return FoodOrder.objects.filter(food_event=self.food_event)\n\n    def get_object(self):\n        queryset = self.filter_queryset(self.get_queryset())\n        obj = get_object_or_404(queryset, member=self.request.member)\n\n        # May raise a permission denied\n        self.check_object_permissions(self.request, obj)\n\n        return obj\n\n    def dispatch(self, request, *args, **kwargs):\n        self.food_event = get_object_or_404(FoodEvent, pk=self.kwargs.get(\"pk\"))\n        try:\n            return super().dispatch(request, *args, **kwargs)\n        except PaymentError as e:\n            return Response(\n                str(e),\n                status=status.HTTP_403_FORBIDDEN,\n            )\n\n    def update(self, request, *args, **kwargs):\n        instance = self.get_object()\n\n        if instance.payment:\n            delete_payment(instance, member=request.member, ignore_change_window=True)\n\n        super().update(request, *args, **kwargs)\n\n        return Response(\n            FoodOrderSerializer(instance, context=self.get_serializer_context()).data\n        )\n\n    def create(self, request, *args, **kwargs):\n        serializer = self.get_serializer(data=request.data)\n        serializer.is_valid(raise_exception=True)\n        self.perform_create(serializer)\n        return Response(\n            FoodOrderSerializer(\n                serializer.instance, context=self.get_serializer_context()\n            ).data,\n            status=status.HTTP_201_CREATED,\n        )\n", "path": "website/pizzas/api/v2/views.py"}, {"content": "\"\"\"Views provided by the pizzas package.\"\"\"\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views.decorators.http import require_http_methods\n\nfrom payments.exceptions import PaymentError\nfrom payments.services import delete_payment\n\nfrom .models import FoodEvent, FoodOrder, Product\n\n\n@login_required\ndef index(request):\n    \"\"\"Overview of user order for a pizza event.\"\"\"\n    products = Product.available_products.order_by(\"name\")\n    if not request.user.has_perm(\"pizzas.order_restricted_products\"):\n        products = products.exclude(restricted=True)\n    event = FoodEvent.current()\n    try:\n        obj = FoodOrder.objects.get(food_event=event, member=request.member)\n    except FoodOrder.DoesNotExist:\n        obj = None\n    context = {\"event\": event, \"products\": products, \"order\": obj}\n    return render(request, \"pizzas/index.html\", context)\n\n\n@require_http_methods([\"POST\"])\ndef cancel_order(request):\n    \"\"\"View that cancels a user's order.\"\"\"\n    if \"order\" in request.POST:\n        try:\n            order = get_object_or_404(FoodOrder, pk=int(request.POST[\"order\"]))\n            if not order.can_be_changed:\n                messages.error(request, _(\"You can no longer cancel.\"))\n            elif order.member == request.member:\n                try:\n                    order.delete()\n                    messages.success(request, _(\"Your order has been cancelled.\"))\n                except PaymentError as e:\n                    messages.error(request, str(e))\n        except Http404:\n            messages.error(request, _(\"Your order could not be found.\"))\n    return redirect(\"pizzas:index\")\n\n\n@login_required\ndef place_order(request):\n    \"\"\"View that shows the detail of the current order.\"\"\"\n    event = FoodEvent.current()\n    if not event:\n        return redirect(\"pizzas:index\")\n\n    try:\n        obj = FoodOrder.objects.get(food_event=event, member=request.member)\n        current_order_locked = not obj.can_be_changed\n    except FoodOrder.DoesNotExist:\n        obj = None\n        current_order_locked = False\n\n    if \"product\" in request.POST and not current_order_locked:\n        productset = Product.available_products.all()\n        if not request.user.has_perm(\"pizzas.order_restricted_products\"):\n            productset = productset.exclude(restricted=True)\n        try:\n            product = productset.get(pk=int(request.POST[\"product\"]))\n        except Product.DoesNotExist as e:\n            raise Http404(\"Pizza does not exist\") from e\n        if not obj:\n            obj = FoodOrder(food_event=event, member=request.member)\n        obj.product = product\n        if obj.payment:\n            try:\n                delete_payment(obj, member=request.member, ignore_change_window=True)\n            except PaymentError:\n                messages.error(\n                    request,\n                    _(\"Your order could not be updated because it was already paid.\"),\n                )\n                return redirect(\"pizzas:index\")\n        obj.save()\n    return redirect(\"pizzas:index\")\n", "path": "website/pizzas/views.py"}], "after_files": [{"content": "from django.db.models import Prefetch\nfrom django.utils import timezone\n\nfrom oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope\nfrom rest_framework import filters as framework_filters\nfrom rest_framework import status\nfrom rest_framework.exceptions import PermissionDenied\nfrom rest_framework.generics import (\n    CreateAPIView,\n    DestroyAPIView,\n    ListAPIView,\n    RetrieveAPIView,\n    UpdateAPIView,\n    get_object_or_404,\n)\nfrom rest_framework.response import Response\n\nfrom events.models.event_registration import EventRegistration\nfrom payments.exceptions import PaymentError\nfrom payments.services import delete_payment\nfrom pizzas.api.v2 import filters\nfrom pizzas.api.v2.serializers import (\n    FoodOrderCreateSerializer,\n    FoodOrderSerializer,\n    FoodOrderUpdateSerializer,\n    ProductSerializer,\n)\nfrom pizzas.api.v2.serializers.food_event import FoodEventSerializer\nfrom pizzas.models import FoodEvent, FoodOrder, Product\nfrom thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod\n\n\nclass FoodEventListView(ListAPIView):\n    \"\"\"Returns an overview of all food events.\"\"\"\n\n    serializer_class = FoodEventSerializer\n    filter_backends = (\n        framework_filters.OrderingFilter,\n        filters.FoodEventDateFilterBackend,\n    )\n    ordering_fields = (\"start\", \"end\")\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n    def get_queryset(self):\n        events = FoodEvent.objects.all()\n        if self.request.member:\n            events = events.prefetch_related(\n                Prefetch(\n                    \"event__eventregistration_set\",\n                    to_attr=\"member_registration\",\n                    queryset=EventRegistration.objects.filter(\n                        member=self.request.member\n                    ).select_properties(\"queue_position\"),\n                )\n            )\n        return events\n\n\nclass FoodEventDetailView(RetrieveAPIView):\n    \"\"\"Returns one single food event.\"\"\"\n\n    serializer_class = FoodEventSerializer\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n    def get_queryset(self):\n        events = FoodEvent.objects.all()\n        if self.request.member:\n            events = events.prefetch_related(\n                Prefetch(\n                    \"event__eventregistration_set\",\n                    to_attr=\"member_registration\",\n                    queryset=EventRegistration.objects.filter(\n                        member=self.request.member\n                    ).select_properties(\"queue_position\"),\n                )\n            )\n        return events\n\n\nclass FoodEventProductsListView(ListAPIView):\n    \"\"\"Returns an overview of all products.\"\"\"\n\n    serializer_class = ProductSerializer\n    queryset = Product.available_products.all()\n    filter_backends = (framework_filters.SearchFilter,)\n    search_fields = (\"name\",)\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n    ]\n    required_scopes = [\"food:read\"]\n\n\nclass FoodEventOrderDetailView(\n    RetrieveAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView\n):\n    \"\"\"Returns details of a food order.\"\"\"\n\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScopeForMethod,\n    ]\n    required_scopes_per_method = {\n        \"GET\": [\"food:read\"],\n        \"POST\": [\"food:order\"],\n        \"PUT\": [\"food:order\"],\n        \"PATCH\": [\"food:order\"],\n        \"DELETE\": [\"food:order\"],\n    }\n\n    def get_serializer_class(self):\n        if self.request.method.lower() == \"get\":\n            return FoodOrderSerializer\n        if self.request.method.lower() == \"post\":\n            return FoodOrderCreateSerializer\n        return FoodOrderUpdateSerializer\n\n    def get_queryset(self):\n        return FoodOrder.objects.filter(food_event=self.food_event)\n\n    def get_object(self):\n        queryset = self.filter_queryset(self.get_queryset())\n        obj = get_object_or_404(queryset, member=self.request.member)\n\n        # May raise a permission denied\n        self.check_object_permissions(self.request, obj)\n\n        return obj\n\n    def dispatch(self, request, *args, **kwargs):\n        self.food_event = get_object_or_404(FoodEvent, pk=self.kwargs.get(\"pk\"))\n        try:\n            return super().dispatch(request, *args, **kwargs)\n        except PaymentError as e:\n            return Response(\n                str(e),\n                status=status.HTTP_403_FORBIDDEN,\n            )\n\n    def update(self, request, *args, **kwargs):\n        instance = self.get_object()\n        if instance.event.has_ended:\n            raise PermissionDenied\n        if instance.payment:\n            delete_payment(instance, member=request.member, ignore_change_window=True)\n\n        super().update(request, *args, **kwargs)\n\n        return Response(\n            FoodOrderSerializer(instance, context=self.get_serializer_context()).data\n        )\n\n    def create(self, request, *args, **kwargs):\n        if self.food_event.start > timezone.now():\n            raise PermissionDenied(\"You cannot order food yet\")\n        if self.food_event.has_ended:\n            raise PermissionDenied(\"Event has ended\")\n\n        event = self.food_event.event\n        if event.registration_required:\n            registration = event.registrations.filter(\n                member=request.member, date_cancelled=None\n            ).first()\n            if registration is None or not registration.is_invited:\n                raise PermissionDenied(\"You are not registered for this event\")\n\n        serializer = self.get_serializer(data=request.data)\n        serializer.is_valid(raise_exception=True)\n        self.perform_create(serializer)\n        return Response(\n            FoodOrderSerializer(\n                serializer.instance, context=self.get_serializer_context()\n            ).data,\n            status=status.HTTP_201_CREATED,\n        )\n", "path": "website/pizzas/api/v2/views.py"}, {"content": "\"\"\"Views provided by the pizzas package.\"\"\"\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils import timezone\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views.decorators.http import require_http_methods\n\nfrom payments.exceptions import PaymentError\nfrom payments.services import delete_payment\n\nfrom .models import FoodEvent, FoodOrder, Product\n\n\n@login_required\ndef index(request):\n    \"\"\"Overview of user order for a pizza event.\"\"\"\n    products = Product.available_products.order_by(\"name\")\n    if not request.user.has_perm(\"pizzas.order_restricted_products\"):\n        products = products.exclude(restricted=True)\n    event = FoodEvent.current()\n    try:\n        obj = FoodOrder.objects.get(food_event=event, member=request.member)\n    except FoodOrder.DoesNotExist:\n        obj = None\n\n    registrated_required = (\n        event is not None\n        and event.event is not None\n        and event.event.registration_required\n    )\n    not_registered = False\n    if registrated_required:\n        registration = event.event.registrations.filter(\n            member=request.member, date_cancelled=None\n        ).first()\n\n        if registration is None or not registration.is_invited:\n            not_registered = True\n\n    context = {\n        \"event\": event,\n        \"products\": products,\n        \"order\": obj,\n        \"not_registered\": not_registered,\n    }\n    return render(request, \"pizzas/index.html\", context)\n\n\n@require_http_methods([\"POST\"])\ndef cancel_order(request):\n    \"\"\"View that cancels a user's order.\"\"\"\n    if \"order\" in request.POST:\n        try:\n            order = get_object_or_404(FoodOrder, pk=int(request.POST[\"order\"]))\n            if not order.can_be_changed:\n                messages.error(request, _(\"You can no longer cancel.\"))\n            elif order.member == request.member:\n                try:\n                    order.delete()\n                    messages.success(request, _(\"Your order has been cancelled.\"))\n                except PaymentError as e:\n                    messages.error(request, str(e))\n        except Http404:\n            messages.error(request, _(\"Your order could not be found.\"))\n    return redirect(\"pizzas:index\")\n\n\n@login_required\ndef place_order(request):\n    \"\"\"View that shows the detail of the current order.\"\"\"\n    event = FoodEvent.current()\n\n    if not event:\n        return redirect(\"pizzas:index\")\n\n    if event.start > timezone.now():\n        return redirect(\"pizzas:index\")\n\n    if event.has_ended:\n        return redirect(\"pizzas:index\")\n\n    if event.event.registration_required:\n        registration = event.event.registrations.filter(\n            member=request.member, date_cancelled=None\n        ).first()\n        if registration is None or not registration.is_invited:\n            return redirect(\"pizzas:index\")\n\n    try:\n        obj = FoodOrder.objects.get(food_event=event, member=request.member)\n        current_order_locked = not obj.can_be_changed\n    except FoodOrder.DoesNotExist:\n        obj = None\n        current_order_locked = False\n\n    if \"product\" in request.POST and not current_order_locked:\n        productset = Product.available_products.all()\n        if not request.user.has_perm(\"pizzas.order_restricted_products\"):\n            productset = productset.exclude(restricted=True)\n        try:\n            product = productset.get(pk=int(request.POST[\"product\"]))\n        except Product.DoesNotExist as e:\n            raise Http404(\"Pizza does not exist\") from e\n        if not obj:\n            obj = FoodOrder(food_event=event, member=request.member)\n        obj.product = product\n        if obj.payment:\n            try:\n                delete_payment(obj, member=request.member, ignore_change_window=True)\n            except PaymentError:\n                messages.error(\n                    request,\n                    _(\"Your order could not be updated because it was already paid.\"),\n                )\n                return redirect(\"pizzas:index\")\n        obj.save()\n    return redirect(\"pizzas:index\")\n", "path": "website/pizzas/views.py"}]}