We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Catch ValueError when updating orders if order is paid
This error should be caught.

Sentry Issue: [CONCREXIT-6V](https://sentry.io/organizations/thalia/issues/2472850301/?referrer=github_integration)

```
ValueError: This order has already been paid for.
(12 additional frame(s) were not displayed)
...
  File "rest_framework/serializers.py", line 200, in save
    self.instance = self.update(self.instance, validated_data)
  File "sales/api/v2/admin/serializers/order.py", line 151, in update
    OrderItemSerializer(item, context={"order": instance}).update(
  File "sales/api/v2/admin/serializers/order.py", line 66, in update
    super().update(instance, validated_data)
  File "rest_framework/serializers.py", line 983, in update
    instance.save()
  File "sales/models/order.py", line 215, in save
    raise ValueError("This order has already been paid for.")
```

--- 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/sales/api/v2/admin/serializers/order.py`
Content:
```
1 from django.core.exceptions import ObjectDoesNotExist
2 from django.utils.encoding import smart_str
3 from rest_framework import serializers
4 
5 from members.api.v2.serializers.member import MemberSerializer
6 from payments.api.v2.serializers import PaymentSerializer
7 from sales.models.order import Order, OrderItem
8 from sales.models.product import ProductListItem
9 
10 
11 class ProductNameRelatedField(serializers.SlugRelatedField):
12     def get_queryset(self):
13         shift = self.root.context.get("shift", None)
14         if shift is None:
15             shift = self.root.instance.shift
16         return ProductListItem.objects.filter(product_list=shift.product_list)
17 
18     def to_internal_value(self, data):
19         if type(data) is ProductListItem:
20             return data
21 
22         queryset = self.get_queryset()
23         try:
24             return queryset.get(product__name=data)
25         except ObjectDoesNotExist:
26             self.fail(
27                 "does_not_exist", slug_name=self.slug_field, value=smart_str(data)
28             )
29         except (TypeError, ValueError):
30             self.fail("invalid")
31 
32     def to_representation(self, obj):
33         return obj.product.name
34 
35 
36 class OrderItemSerializer(serializers.ModelSerializer):
37     """Serializer for order items."""
38 
39     class Meta:
40         model = OrderItem
41         fields = ("product", "amount", "total")
42         read_only_fields = ("total",)
43 
44     product = ProductNameRelatedField("product")
45 
46     total = serializers.DecimalField(
47         max_digits=6, decimal_places=2, min_value=0, read_only=True
48     )
49 
50     def get_fields(self):
51         fields = super().get_fields()
52         request = self.context.get("request", None)
53         if request and request.user and request.user.has_perm("sales.custom_prices"):
54             fields["total"].read_only = False
55         return fields
56 
57     def create(self, validated_data, **kwargs):
58         order = self.context["order"]
59         item = OrderItem.objects.create(order=order, **validated_data)
60         return item
61 
62     def update(self, instance, validated_data, **kwargs):
63         order = self.context["order"]
64         instance.order = order
65         instance.total = None  # Always recalculate the total amount if updating using API (note the difference from the model that only recalculates if the total is None, to deal with historic data and allow for special discounts)
66         super().update(instance, validated_data)
67         return instance
68 
69 
70 class OrderSerializer(serializers.ModelSerializer):
71     """Serializer for orders."""
72 
73     class Meta:
74         model = Order
75         fields = (
76             "pk",
77             "shift",
78             "created_at",
79             "order_items",
80             "order_description",
81             "age_restricted",
82             "subtotal",
83             "discount",
84             "total_amount",
85             "num_items",
86             "payment",
87             "payer",
88             "payment_url",
89         )
90         read_only_fields = (
91             "pk",
92             "created_at",
93             "payment",
94             "num_items",
95             "order_description",
96         )
97 
98     shift = serializers.PrimaryKeyRelatedField(read_only=True)
99 
100     age_restricted = serializers.BooleanField(read_only=True)
101 
102     order_items = OrderItemSerializer(many=True, required=False)
103 
104     subtotal = serializers.DecimalField(
105         max_digits=6, decimal_places=2, min_value=0, read_only=True
106     )
107 
108     discount = serializers.DecimalField(
109         max_digits=6, decimal_places=2, min_value=0, read_only=True
110     )
111 
112     total_amount = serializers.DecimalField(
113         max_digits=6, decimal_places=2, min_value=0, read_only=True
114     )
115 
116     payment = PaymentSerializer(read_only=True)
117 
118     payer = MemberSerializer(read_only=True)
119 
120     payment_url = serializers.URLField(read_only=True)
121 
122     def get_fields(self):
123         fields = super().get_fields()
124         request = self.context.get("request", None)
125         if request and request.user and request.user.has_perm("sales.custom_prices"):
126             try:
127                 fields["discount"].read_only = False
128             except KeyError:
129                 pass
130         return fields
131 
132     def create(self, validated_data):
133         shift = self.context["shift"]
134         order = Order.objects.create(shift=shift)
135         if "order_items" in validated_data:
136             items_data = validated_data.pop("order_items")
137             for item_data in items_data:
138                 OrderItem.objects.create(order=order, **item_data)
139         return order
140 
141     def update(self, instance, validated_data):
142         # Update the order items for an order
143         if "order_items" in validated_data:
144             items_data = validated_data.pop("order_items")
145             current_items = list(instance.order_items.all())
146 
147             # Overwrite all existing order items by the newly provided ones
148             for item_data in items_data:
149                 if len(current_items) > 0:
150                     item = current_items.pop(0)
151                     OrderItemSerializer(item, context={"order": instance}).update(
152                         item, item_data
153                     )
154                 else:
155                     # Create new order items if required
156                     OrderItemSerializer(context={"order": instance}).create(
157                         validated_data=item_data
158                     )
159 
160             # Delete all order items that we have not updated
161             for i in current_items:
162                 i.delete()
163 
164         # Update other fields of the order as default
165         instance = super().update(instance, validated_data)
166         instance = Order.objects.get(
167             pk=instance.pk
168         )  # refresh from database to update queryable properties
169         return instance
170 
171 
172 class OrderListSerializer(OrderSerializer):
173     class Meta:
174         model = Order
175         fields = (
176             "pk",
177             "created_at",
178             "total_amount",
179             "num_items",
180         )
181         read_only_fields = (
182             "pk",
183             "created_at",
184             "total_amount",
185             "num_items",
186         )
187
```
--- 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/sales/api/v2/admin/serializers/order.py b/website/sales/api/v2/admin/serializers/order.py
--- a/website/sales/api/v2/admin/serializers/order.py
+++ b/website/sales/api/v2/admin/serializers/order.py
@@ -1,6 +1,7 @@
-from django.core.exceptions import ObjectDoesNotExist
+from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.utils.encoding import smart_str
 from rest_framework import serializers
+from rest_framework.settings import api_settings
 
 from members.api.v2.serializers.member import MemberSerializer
 from payments.api.v2.serializers import PaymentSerializer
@@ -63,7 +64,10 @@
         order = self.context["order"]
         instance.order = order
         instance.total = None  # Always recalculate the total amount if updating using API (note the difference from the model that only recalculates if the total is None, to deal with historic data and allow for special discounts)
-        super().update(instance, validated_data)
+        try:
+            super().update(instance, validated_data)
+        except ValueError as e:
+            raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [e]})
         return instance

{"golden_diff": "diff --git a/website/sales/api/v2/admin/serializers/order.py b/website/sales/api/v2/admin/serializers/order.py\n--- a/website/sales/api/v2/admin/serializers/order.py\n+++ b/website/sales/api/v2/admin/serializers/order.py\n@@ -1,6 +1,7 @@\n-from django.core.exceptions import ObjectDoesNotExist\n+from django.core.exceptions import ObjectDoesNotExist, ValidationError\n from django.utils.encoding import smart_str\n from rest_framework import serializers\n+from rest_framework.settings import api_settings\n \n from members.api.v2.serializers.member import MemberSerializer\n from payments.api.v2.serializers import PaymentSerializer\n@@ -63,7 +64,10 @@\n         order = self.context[\"order\"]\n         instance.order = order\n         instance.total = None  # Always recalculate the total amount if updating using API (note the difference from the model that only recalculates if the total is None, to deal with historic data and allow for special discounts)\n-        super().update(instance, validated_data)\n+        try:\n+            super().update(instance, validated_data)\n+        except ValueError as e:\n+            raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [e]})\n         return instance\n", "issue": "Catch ValueError when updating orders if order is paid\nThis error should be caught.\n\nSentry Issue: [CONCREXIT-6V](https://sentry.io/organizations/thalia/issues/2472850301/?referrer=github_integration)\n\n```\nValueError: This order has already been paid for.\n(12 additional frame(s) were not displayed)\n...\n  File \"rest_framework/serializers.py\", line 200, in save\n    self.instance = self.update(self.instance, validated_data)\n  File \"sales/api/v2/admin/serializers/order.py\", line 151, in update\n    OrderItemSerializer(item, context={\"order\": instance}).update(\n  File \"sales/api/v2/admin/serializers/order.py\", line 66, in update\n    super().update(instance, validated_data)\n  File \"rest_framework/serializers.py\", line 983, in update\n    instance.save()\n  File \"sales/models/order.py\", line 215, in save\n    raise ValueError(\"This order has already been paid for.\")\n```\n", "before_files": [{"content": "from django.core.exceptions import ObjectDoesNotExist\nfrom django.utils.encoding import smart_str\nfrom rest_framework import serializers\n\nfrom members.api.v2.serializers.member import MemberSerializer\nfrom payments.api.v2.serializers import PaymentSerializer\nfrom sales.models.order import Order, OrderItem\nfrom sales.models.product import ProductListItem\n\n\nclass ProductNameRelatedField(serializers.SlugRelatedField):\n    def get_queryset(self):\n        shift = self.root.context.get(\"shift\", None)\n        if shift is None:\n            shift = self.root.instance.shift\n        return ProductListItem.objects.filter(product_list=shift.product_list)\n\n    def to_internal_value(self, data):\n        if type(data) is ProductListItem:\n            return data\n\n        queryset = self.get_queryset()\n        try:\n            return queryset.get(product__name=data)\n        except ObjectDoesNotExist:\n            self.fail(\n                \"does_not_exist\", slug_name=self.slug_field, value=smart_str(data)\n            )\n        except (TypeError, ValueError):\n            self.fail(\"invalid\")\n\n    def to_representation(self, obj):\n        return obj.product.name\n\n\nclass OrderItemSerializer(serializers.ModelSerializer):\n    \"\"\"Serializer for order items.\"\"\"\n\n    class Meta:\n        model = OrderItem\n        fields = (\"product\", \"amount\", \"total\")\n        read_only_fields = (\"total\",)\n\n    product = ProductNameRelatedField(\"product\")\n\n    total = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    def get_fields(self):\n        fields = super().get_fields()\n        request = self.context.get(\"request\", None)\n        if request and request.user and request.user.has_perm(\"sales.custom_prices\"):\n            fields[\"total\"].read_only = False\n        return fields\n\n    def create(self, validated_data, **kwargs):\n        order = self.context[\"order\"]\n        item = OrderItem.objects.create(order=order, **validated_data)\n        return item\n\n    def update(self, instance, validated_data, **kwargs):\n        order = self.context[\"order\"]\n        instance.order = order\n        instance.total = None  # Always recalculate the total amount if updating using API (note the difference from the model that only recalculates if the total is None, to deal with historic data and allow for special discounts)\n        super().update(instance, validated_data)\n        return instance\n\n\nclass OrderSerializer(serializers.ModelSerializer):\n    \"\"\"Serializer for orders.\"\"\"\n\n    class Meta:\n        model = Order\n        fields = (\n            \"pk\",\n            \"shift\",\n            \"created_at\",\n            \"order_items\",\n            \"order_description\",\n            \"age_restricted\",\n            \"subtotal\",\n            \"discount\",\n            \"total_amount\",\n            \"num_items\",\n            \"payment\",\n            \"payer\",\n            \"payment_url\",\n        )\n        read_only_fields = (\n            \"pk\",\n            \"created_at\",\n            \"payment\",\n            \"num_items\",\n            \"order_description\",\n        )\n\n    shift = serializers.PrimaryKeyRelatedField(read_only=True)\n\n    age_restricted = serializers.BooleanField(read_only=True)\n\n    order_items = OrderItemSerializer(many=True, required=False)\n\n    subtotal = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    discount = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    total_amount = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    payment = PaymentSerializer(read_only=True)\n\n    payer = MemberSerializer(read_only=True)\n\n    payment_url = serializers.URLField(read_only=True)\n\n    def get_fields(self):\n        fields = super().get_fields()\n        request = self.context.get(\"request\", None)\n        if request and request.user and request.user.has_perm(\"sales.custom_prices\"):\n            try:\n                fields[\"discount\"].read_only = False\n            except KeyError:\n                pass\n        return fields\n\n    def create(self, validated_data):\n        shift = self.context[\"shift\"]\n        order = Order.objects.create(shift=shift)\n        if \"order_items\" in validated_data:\n            items_data = validated_data.pop(\"order_items\")\n            for item_data in items_data:\n                OrderItem.objects.create(order=order, **item_data)\n        return order\n\n    def update(self, instance, validated_data):\n        # Update the order items for an order\n        if \"order_items\" in validated_data:\n            items_data = validated_data.pop(\"order_items\")\n            current_items = list(instance.order_items.all())\n\n            # Overwrite all existing order items by the newly provided ones\n            for item_data in items_data:\n                if len(current_items) > 0:\n                    item = current_items.pop(0)\n                    OrderItemSerializer(item, context={\"order\": instance}).update(\n                        item, item_data\n                    )\n                else:\n                    # Create new order items if required\n                    OrderItemSerializer(context={\"order\": instance}).create(\n                        validated_data=item_data\n                    )\n\n            # Delete all order items that we have not updated\n            for i in current_items:\n                i.delete()\n\n        # Update other fields of the order as default\n        instance = super().update(instance, validated_data)\n        instance = Order.objects.get(\n            pk=instance.pk\n        )  # refresh from database to update queryable properties\n        return instance\n\n\nclass OrderListSerializer(OrderSerializer):\n    class Meta:\n        model = Order\n        fields = (\n            \"pk\",\n            \"created_at\",\n            \"total_amount\",\n            \"num_items\",\n        )\n        read_only_fields = (\n            \"pk\",\n            \"created_at\",\n            \"total_amount\",\n            \"num_items\",\n        )\n", "path": "website/sales/api/v2/admin/serializers/order.py"}], "after_files": [{"content": "from django.core.exceptions import ObjectDoesNotExist, ValidationError\nfrom django.utils.encoding import smart_str\nfrom rest_framework import serializers\nfrom rest_framework.settings import api_settings\n\nfrom members.api.v2.serializers.member import MemberSerializer\nfrom payments.api.v2.serializers import PaymentSerializer\nfrom sales.models.order import Order, OrderItem\nfrom sales.models.product import ProductListItem\n\n\nclass ProductNameRelatedField(serializers.SlugRelatedField):\n    def get_queryset(self):\n        shift = self.root.context.get(\"shift\", None)\n        if shift is None:\n            shift = self.root.instance.shift\n        return ProductListItem.objects.filter(product_list=shift.product_list)\n\n    def to_internal_value(self, data):\n        if type(data) is ProductListItem:\n            return data\n\n        queryset = self.get_queryset()\n        try:\n            return queryset.get(product__name=data)\n        except ObjectDoesNotExist:\n            self.fail(\n                \"does_not_exist\", slug_name=self.slug_field, value=smart_str(data)\n            )\n        except (TypeError, ValueError):\n            self.fail(\"invalid\")\n\n    def to_representation(self, obj):\n        return obj.product.name\n\n\nclass OrderItemSerializer(serializers.ModelSerializer):\n    \"\"\"Serializer for order items.\"\"\"\n\n    class Meta:\n        model = OrderItem\n        fields = (\"product\", \"amount\", \"total\")\n        read_only_fields = (\"total\",)\n\n    product = ProductNameRelatedField(\"product\")\n\n    total = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    def get_fields(self):\n        fields = super().get_fields()\n        request = self.context.get(\"request\", None)\n        if request and request.user and request.user.has_perm(\"sales.custom_prices\"):\n            fields[\"total\"].read_only = False\n        return fields\n\n    def create(self, validated_data, **kwargs):\n        order = self.context[\"order\"]\n        item = OrderItem.objects.create(order=order, **validated_data)\n        return item\n\n    def update(self, instance, validated_data, **kwargs):\n        order = self.context[\"order\"]\n        instance.order = order\n        instance.total = None  # Always recalculate the total amount if updating using API (note the difference from the model that only recalculates if the total is None, to deal with historic data and allow for special discounts)\n        try:\n            super().update(instance, validated_data)\n        except ValueError as e:\n            raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [e]})\n        return instance\n\n\nclass OrderSerializer(serializers.ModelSerializer):\n    \"\"\"Serializer for orders.\"\"\"\n\n    class Meta:\n        model = Order\n        fields = (\n            \"pk\",\n            \"shift\",\n            \"created_at\",\n            \"order_items\",\n            \"order_description\",\n            \"age_restricted\",\n            \"subtotal\",\n            \"discount\",\n            \"total_amount\",\n            \"num_items\",\n            \"payment\",\n            \"payer\",\n            \"payment_url\",\n        )\n        read_only_fields = (\n            \"pk\",\n            \"created_at\",\n            \"payment\",\n            \"num_items\",\n            \"order_description\",\n        )\n\n    shift = serializers.PrimaryKeyRelatedField(read_only=True)\n\n    age_restricted = serializers.BooleanField(read_only=True)\n\n    order_items = OrderItemSerializer(many=True, required=False)\n\n    subtotal = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    discount = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    total_amount = serializers.DecimalField(\n        max_digits=6, decimal_places=2, min_value=0, read_only=True\n    )\n\n    payment = PaymentSerializer(read_only=True)\n\n    payer = MemberSerializer(read_only=True)\n\n    payment_url = serializers.URLField(read_only=True)\n\n    def get_fields(self):\n        fields = super().get_fields()\n        request = self.context.get(\"request\", None)\n        if request and request.user and request.user.has_perm(\"sales.custom_prices\"):\n            try:\n                fields[\"discount\"].read_only = False\n            except KeyError:\n                pass\n        return fields\n\n    def create(self, validated_data):\n        shift = self.context[\"shift\"]\n        order = Order.objects.create(shift=shift)\n        if \"order_items\" in validated_data:\n            items_data = validated_data.pop(\"order_items\")\n            for item_data in items_data:\n                OrderItem.objects.create(order=order, **item_data)\n        return order\n\n    def update(self, instance, validated_data):\n        # Update the order items for an order\n        if \"order_items\" in validated_data:\n            items_data = validated_data.pop(\"order_items\")\n            current_items = list(instance.order_items.all())\n\n            # Overwrite all existing order items by the newly provided ones\n            for item_data in items_data:\n                if len(current_items) > 0:\n                    item = current_items.pop(0)\n                    OrderItemSerializer(item, context={\"order\": instance}).update(\n                        item, item_data\n                    )\n                else:\n                    # Create new order items if required\n                    OrderItemSerializer(context={\"order\": instance}).create(\n                        validated_data=item_data\n                    )\n\n            # Delete all order items that we have not updated\n            for i in current_items:\n                i.delete()\n\n        # Update other fields of the order as default\n        instance = super().update(instance, validated_data)\n        instance = Order.objects.get(\n            pk=instance.pk\n        )  # refresh from database to update queryable properties\n        return instance\n\n\nclass OrderListSerializer(OrderSerializer):\n    class Meta:\n        model = Order\n        fields = (\n            \"pk\",\n            \"created_at\",\n            \"total_amount\",\n            \"num_items\",\n        )\n        read_only_fields = (\n            \"pk\",\n            \"created_at\",\n            \"total_amount\",\n            \"num_items\",\n        )\n", "path": "website/sales/api/v2/admin/serializers/order.py"}]}