diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index 5241353695..345c9d7176 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -1439,6 +1439,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer): if not pos.item.tax_rule or pos.item.tax_rule.price_includes_tax: price_after_voucher = max(pos.price, pos.voucher.calculate_price(listed_price)) else: + pos._calculate_tax(invoice_address=ia) price_after_voucher = max(pos.price - pos.tax_value, pos.voucher.calculate_price(listed_price)) else: price_after_voucher = listed_price @@ -1466,7 +1467,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer): answers_data = pos_data.pop('answers', []) use_reusable_medium = pos_data.pop('use_reusable_medium', None) pos = pos_data['__instance'] - pos._calculate_tax() + pos._calculate_tax(invoice_address=ia) if simulate: pos = WrappedModel(pos) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index d92de3c8de..e08b1d63de 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -2582,10 +2582,10 @@ class OrderPosition(AbstractPosition): self.item.id, self.variation.id if self.variation else 0, self.order_id ) - def _calculate_tax(self, tax_rule=None): + def _calculate_tax(self, tax_rule=None, invoice_address=None): self.tax_rule = tax_rule or self.item.tax_rule try: - ia = self.order.invoice_address + ia = invoice_address or self.order.invoice_address except InvoiceAddress.DoesNotExist: ia = None if self.tax_rule: diff --git a/src/tests/api/test_order_create.py b/src/tests/api/test_order_create.py index 3a9c9d0b0e..3e53f7a19a 100644 --- a/src/tests/api/test_order_create.py +++ b/src/tests/api/test_order_create.py @@ -2190,6 +2190,33 @@ def test_order_create_with_seat_consumed_from_cart(token_client, organizer, even assert p.seat == seat +@pytest.mark.django_db +def test_order_create_with_voucher_and_price_set(token_client, organizer, event, item, quota, question): + with scopes_disabled(): + voucher = event.vouchers.create(code="FOOBAR", item=item, price_mode="set", value=0, max_usages=3) + item.tax_rule = event.tax_rules.create(rate=19, price_includes_tax=False) + item.save() + res = copy.deepcopy(ORDER_CREATE_PAYLOAD) + res['positions'][0]['item'] = item.pk + res['positions'][0]['voucher'] = voucher.code + res['positions'][0]['price'] = '0.00' + res['positions'][0].pop("tax_rate", None) + res['positions'][0].pop("tax_rule", None) + res['positions'][0].pop("tax_value", None) + res['positions'][0]['answers'][0]['question'] = question.pk + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/orders/'.format( + organizer.slug, event.slug + ), format='json', data=res + ) + assert resp.status_code == 201 + with scopes_disabled(): + o = Order.objects.get(code=resp.data['code']) + p = o.positions.first() + assert p.voucher == voucher + assert p.price == Decimal("0.00") + + @pytest.mark.django_db def test_order_create_with_voucher_consumed_from_cart(token_client, organizer, event, item, quota, question): with scopes_disabled():