From 0d35064d2194b2b7cb14f4fb3b57079ae1b9feeb Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Tue, 2 Jun 2020 16:48:52 +0200 Subject: [PATCH] Order create API: Fix addon_to in simulated mode PRETIXEU-275 --- src/pretix/api/serializers/order.py | 13 +++++++- src/pretix/api/views/order.py | 6 ++-- src/tests/api/test_orders.py | 52 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index 328534d9b..1065feb32 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -416,6 +416,14 @@ class OrderSerializer(I18nAwareModelSerializer): return instance +class SimulatedOrderPositionSerializer(OrderPositionSerializer): + addon_to = serializers.SlugRelatedField(read_only=True, slug_field='positionid') + + +class SimulatedOrderSerializer(OrderSerializer): + positions = SimulatedOrderPositionSerializer(many=True, read_only=True) + + class PriceCalcSerializer(serializers.Serializer): item = serializers.PrimaryKeyRelatedField(queryset=Item.objects.none(), required=False, allow_null=True) variation = serializers.PrimaryKeyRelatedField(queryset=ItemVariation.objects.none(), required=False, allow_null=True) @@ -963,7 +971,10 @@ class OrderCreateSerializer(I18nAwareModelSerializer): else: pos.order = order if addon_to: - pos.addon_to = pos_map[addon_to] + if simulate: + pos.addon_to = pos_map[addon_to]._wrapped + else: + pos.addon_to = pos_map[addon_to] if pos.price is None: price = get_price( diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 398836d78..abb61824d 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -26,7 +26,7 @@ from pretix.api.serializers.order import ( InvoiceSerializer, OrderCreateSerializer, OrderPaymentCreateSerializer, OrderPaymentSerializer, OrderPositionSerializer, OrderRefundCreateSerializer, OrderRefundSerializer, OrderSerializer, - PriceCalcSerializer, + PriceCalcSerializer, SimulatedOrderSerializer, ) from pretix.base.i18n import language from pretix.base.models import ( @@ -488,10 +488,12 @@ class OrderViewSet(viewsets.ModelViewSet): self.perform_create(serializer) send_mail = serializer._send_mail order = serializer.instance - serializer = OrderSerializer(order, context=serializer.context) if not order.pk: # Simulation + serializer = SimulatedOrderSerializer(order, context=serializer.context) return Response(serializer.data, status=status.HTTP_201_CREATED) + else: + serializer = OrderSerializer(order, context=serializer.context) order.log_action( 'pretix.event.order.placed', diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py index 36ce29055..63b83907f 100644 --- a/src/tests/api/test_orders.py +++ b/src/tests/api/test_orders.py @@ -1664,6 +1664,58 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques } +@pytest.mark.django_db +def test_order_create_positionids_addons_simulated(token_client, organizer, event, item, quota): + res = copy.deepcopy(ORDER_CREATE_PAYLOAD) + res['positions'] = [ + { + "positionid": 1, + "item": item.pk, + "variation": None, + "price": "23.00", + "attendee_name_parts": {"full_name": "Peter"}, + "attendee_email": None, + "addon_to": None, + "answers": [], + "subevent": None + }, + { + "positionid": 2, + "item": item.pk, + "variation": None, + "price": "23.00", + "attendee_name_parts": {"full_name": "Peter"}, + "attendee_email": None, + "addon_to": 1, + "answers": [], + "subevent": None + } + ] + res['simulate'] = True + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/orders/'.format( + organizer.slug, event.slug + ), format='json', data=res + ) + assert resp.status_code == 201 + del resp.data['positions'][0]['secret'] + del resp.data['positions'][1]['secret'] + assert [dict(f) for f in resp.data['positions']] == [ + {'id': 0, 'order': '', 'positionid': 1, 'item': 1, 'variation': None, 'price': '23.00', + 'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'company': None, + 'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None, + 'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', + 'addon_to': None, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None, + 'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False}, + {'id': 0, 'order': '', 'positionid': 2, 'item': 1, 'variation': None, 'price': '23.00', + 'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'company': None, + 'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None, + 'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', + 'addon_to': 1, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None, + 'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False} + ] + + @pytest.mark.django_db def test_order_create_autocheckin(token_client, organizer, event, item, quota, question, clist_autocheckin): res = copy.deepcopy(ORDER_CREATE_PAYLOAD)