From ea7468863395449f245ce4d8c7779e53d5dcb96c Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 14 Feb 2024 13:27:30 +0100 Subject: [PATCH] API: Expose OrderPosition.voucher_budget_use (#3867) --- doc/api/resources/orders.rst | 9 +++++++++ src/pretix/api/serializers/order.py | 4 ++-- src/tests/api/test_giftcards.py | 1 + src/tests/api/test_order_create.py | 17 ++++++++++++----- src/tests/api/test_orders.py | 1 + src/tests/api/test_reusable_media.py | 1 + 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index e08551dbcb..91cb580d0c 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -179,6 +179,11 @@ country string Attendee countr state string Attendee state (ISO 3166-2 code). Only supported in AU, BR, CA, CN, MY, MX, and US, otherwise ``null``. voucher integer Internal ID of the voucher used for this position (or ``null``) +voucher_budget_use money (string) Amount of money discounted by the voucher, corresponding + to how much of the ``budget`` of the voucher is consumed. + **Important:** Do not rely on this amount to be a useful + value if the position's price, product or voucher + are changed *after* the order was created. Can be ``null``. tax_rate decimal (string) VAT rate applied for this position tax_value money (string) VAT included in this position tax_rule integer The ID of the used tax rule (or ``null``) @@ -367,6 +372,7 @@ List of all orders "country": "DE", "state": null, "voucher": null, + "voucher_budget_use": null, "tax_rate": "0.00", "tax_value": "0.00", "tax_rule": null, @@ -589,6 +595,7 @@ Fetching individual orders "country": "DE", "state": null, "voucher": null, + "voucher_budget_use": null, "tax_rate": "0.00", "tax_rule": null, "tax_value": "0.00", @@ -1541,6 +1548,7 @@ List of all order positions }, "attendee_email": null, "voucher": null, + "voucher_budget_use": null, "tax_rate": "0.00", "tax_rule": null, "tax_value": "0.00", @@ -1654,6 +1662,7 @@ Fetching individual positions }, "attendee_email": null, "voucher": null, + "voucher_budget_use": null, "tax_rate": "0.00", "tax_rule": null, "tax_value": "0.00", diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index c6d843fc30..9cfb1c6c77 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -486,11 +486,11 @@ class OrderPositionSerializer(I18nAwareModelSerializer): 'company', 'street', 'zipcode', 'city', 'country', 'state', 'discount', 'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat', 'canceled', - 'valid_from', 'valid_until', 'blocked') + 'valid_from', 'valid_until', 'blocked', 'voucher_budget_use') read_only_fields = ( 'id', 'order', 'positionid', 'item', 'variation', 'price', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', - 'seat', 'canceled', 'discount', 'valid_from', 'valid_until', 'blocked' + 'seat', 'canceled', 'discount', 'valid_from', 'valid_until', 'blocked', 'voucher_budget_use' ) def __init__(self, *args, **kwargs): diff --git a/src/tests/api/test_giftcards.py b/src/tests/api/test_giftcards.py index 74d67dcdc2..58c389bc15 100644 --- a/src/tests/api/test_giftcards.py +++ b/src/tests/api/test_giftcards.py @@ -135,6 +135,7 @@ def test_giftcard_detail_expand(token_client, organizer, event, giftcard): "discount": None, "attendee_email": None, "voucher": None, + "voucher_budget_use": None, "tax_rate": "0.00", "tax_value": "0.00", "secret": op.secret, diff --git a/src/tests/api/test_order_create.py b/src/tests/api/test_order_create.py index 4dacaafaa4..8d11010625 100644 --- a/src/tests/api/test_order_create.py +++ b/src/tests/api/test_order_create.py @@ -341,10 +341,14 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques question.type = Question.TYPE_CHOICE_MULTIPLE question.save() with scopes_disabled(): + voucher = event.vouchers.create(price_mode="set", value=21.50, item=item, budget=Decimal('2.50'), + max_usages=999) opt = question.options.create(answer="L") res['positions'][0]['item'] = item.pk res['positions'][0]['answers'][0]['question'] = question.pk res['positions'][0]['answers'][0]['options'] = [opt.pk] + res['positions'][0]['voucher'] = voucher.code + del res['positions'][0]['price'] res['simulate'] = True resp = token_client.post( '/api/v1/organizers/{}/events/{}/orders/'.format( @@ -391,7 +395,7 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques 'canceled': False } ], - 'total': '23.25', + 'total': '21.75', 'comment': '', "custom_followup_at": None, 'invoice_address': { @@ -416,11 +420,12 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques 'positionid': 1, 'item': item.pk, 'variation': None, - 'price': '23.00', + 'price': '21.50', 'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'attendee_email': None, - 'voucher': None, + 'voucher': voucher.pk, + 'voucher_budget_use': '1.50', 'tax_rate': '0.00', 'tax_value': '0.00', 'addon_to': None, @@ -498,13 +503,13 @@ def test_order_create_positionids_addons_simulated(token_client, organizer, even {'id': 0, 'order': '', 'positionid': 1, 'item': item.pk, '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', 'discount': None, + 'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', 'discount': None, 'voucher_budget_use': None, 'addon_to': None, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None, 'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None}, {'id': 0, 'order': '', 'positionid': 2, 'item': item.pk, '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', 'discount': None, + 'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', 'discount': None, 'voucher_budget_use': None, 'addon_to': 1, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None, 'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None} ] @@ -2558,6 +2563,8 @@ def test_order_create_autopricing_voucher_budget_partially(token_client, organiz ), format='json', data=res ) assert resp.status_code == 201 + assert resp.data["positions"][0]["voucher_budget_use"] == "1.50" + assert resp.data["positions"][1]["voucher_budget_use"] == "1.00" with scopes_disabled(): o = Order.objects.get(code=resp.data['code']) p = o.positions.first() diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py index c209e61e85..78d9d23180 100644 --- a/src/tests/api/test_orders.py +++ b/src/tests/api/test_orders.py @@ -188,6 +188,7 @@ TEST_ORDERPOSITION_RES = { "attendee_name": "Peter", "attendee_email": None, "voucher": None, + "voucher_budget_use": None, "discount": None, "tax_rate": "0.00", "tax_value": "0.00", diff --git a/src/tests/api/test_reusable_media.py b/src/tests/api/test_reusable_media.py index bb27a63efc..9688f2d658 100644 --- a/src/tests/api/test_reusable_media.py +++ b/src/tests/api/test_reusable_media.py @@ -183,6 +183,7 @@ def test_medium_detail(token_client, organizer, event, medium, giftcard, custome "discount": None, "attendee_email": None, "voucher": None, + "voucher_budget_use": None, "tax_rate": "0.00", "tax_value": "0.00", "secret": op.secret,