diff --git a/src/pretix/api/serializers/cart.py b/src/pretix/api/serializers/cart.py index 4a4faaea39..5e900c47ab 100644 --- a/src/pretix/api/serializers/cart.py +++ b/src/pretix/api/serializers/cart.py @@ -237,12 +237,14 @@ class CartPositionCreateSerializer(BaseCartPositionCreateSerializer): for addon_data in addons_data: addon_data['addon_to'] = cp addon_data['is_bundled'] = False + addon_data['cart_id'] = cp.cart_id super().create(addon_data) if bundled_data: for bundle_data in bundled_data: bundle_data['addon_to'] = cp bundle_data['is_bundled'] = True + bundle_data['cart_id'] = cp.cart_id super().create(bundle_data) return cp diff --git a/src/tests/api/test_cart.py b/src/tests/api/test_cart.py index b65bfb2b7a..21af7788bd 100644 --- a/src/tests/api/test_cart.py +++ b/src/tests/api/test_cart.py @@ -1120,6 +1120,7 @@ def test_cartpos_create_bulk_with_addon(token_client, organizer, event, item, qu assert cp1a.item == addon_item assert not cp1a.is_bundled assert cp1a.attendee_name == "Peter's friend" + assert cp1a.cart_id == cp1.cart_id @pytest.mark.django_db @@ -1210,6 +1211,7 @@ def test_cartpos_create_bulk_with_bundled(token_client, organizer, event, item, cp1a = cp1.addons.get() assert cp1a.pk == resp.data['results'][0]['data']['bundled'][0]['id'] assert cp1a.item == bundled_item + assert cp1a.cart_id == cp1.cart_id assert cp1a.is_bundled assert cp1a.attendee_name == "Peter's friend" diff --git a/src/tests/api/test_order_create.py b/src/tests/api/test_order_create.py index 2d94be02f6..8899d69ce7 100644 --- a/src/tests/api/test_order_create.py +++ b/src/tests/api/test_order_create.py @@ -2612,3 +2612,98 @@ def test_order_create_pdf_data(token_client, organizer, event, item, quota, ques ) assert resp.status_code == 201 assert 'secret' in resp.data['positions'][0]['pdf_data'] + + +@pytest.mark.django_db +def test_create_cart_and_consume_cart_with_addons(token_client, organizer, event, item, quota, question): + with scopes_disabled(): + addon_cat = event.categories.create(name='Addons') + addon_item = event.items.create(name='Workshop', default_price=2, category=addon_cat) + item.addons.create(addon_category=addon_cat) + q = event.quotas.create(name="Addon Quota", size=1) + q.items.add(addon_item) + + res = { + 'cart_id': 'aaa@api', + 'item': item.pk, + 'variation': None, + 'price': '23.00', + 'attendee_name_parts': {'full_name': 'Peter'}, + 'attendee_email': None, + 'addon_to': None, + 'subevent': None, + 'expires': (now() + datetime.timedelta(days=1)).isoformat(), + 'includes_tax': True, + 'sales_channel': 'web', + 'answers': [], + 'addons': [ + { + 'item': addon_item.pk, + 'variation': None, + 'price': '1.00', + 'attendee_name_parts': {'full_name': 'Peter\'s friend'}, + 'attendee_email': None, + 'subevent': None, + 'includes_tax': True, + 'answers': [] + } + ], + } + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/cartpositions/bulk_create/'.format( + organizer.slug, event.slug + ), format='json', data=[ + res + ] + ) + assert resp.status_code == 200 + assert len(resp.data['results']) == 1 + assert resp.data['results'][0]['success'] + assert resp.data['results'][0]['data']['addons'] + + 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": addon_item.pk, + "variation": None, + "price": "23.00", + "attendee_name_parts": {"full_name": "Peter"}, + "attendee_email": None, + "addon_to": 1, + "answers": [], + "subevent": None + } + ] + + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/orders/'.format( + organizer.slug, event.slug + ), format='json', data=res + ) + assert resp.status_code == 400 + assert resp.data == { + 'positions': [ + {}, + {'item': ['There is not enough quota available on quota "Addon Quota" to perform the operation.']}, + ] + } + + res['consume_carts'] = ['aaa@api'] + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/orders/'.format( + organizer.slug, event.slug + ), format='json', data=res + ) + assert resp.status_code == 201