diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index 9460c90673..c0171b48a4 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -1104,10 +1104,9 @@ Creating orders pay for the order. Processing of the gift cards stops as soon as the order is payed for. All gift card transactions are listed under ``payments`` in the response. This option can only be used with orders that are in the pending state. - In addition to ``use_gift_cards``, you can provide ``payment_info`` and ``payment_provider`` fields. A matching - payment record for the ``payment_provider`` will be created once all the gift cards have been processed. This - entry's amount is what you'll need to charge your customer. The above-mentioned caveats for ``payment_info`` still - apply. + The ``use_gift_cards`` attribute can not be combined with ``payment_info`` and ``payment_provider`` fields. If the + order isn't completely paid after its creation with ``use_gift_cards``, then a subsequent request to the payment + endpoint is needed. If you want to use add-on products, you need to set the ``positionid`` fields of all positions manually to incrementing integers starting with ``1``. Then, you can reference one of these diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index 249a44bd0f..2ac2ab8ba8 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -1314,6 +1314,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer): simulate = validated_data.pop('simulate', False) gift_card_secrets = validated_data.pop('use_gift_cards') if 'use_gift_cards' in validated_data else [] + if (payment_provider is not None or payment_info != '{}') and len(gift_card_secrets) > 0: + raise ValidationError({"use_gift_cards": ['The attribute use_gift_cards is not compatible with payment_provider or payment_info']}) if validated_data.get('status') != Order.STATUS_PENDING and len(gift_card_secrets) > 0: raise ValidationError({"use_gift_cards": ['The attribute use_gift_cards is only supported for orders that are created as pending']}) if len(set(gift_card_secrets)) != len(gift_card_secrets): diff --git a/src/tests/api/test_order_create.py b/src/tests/api/test_order_create.py index 242894839f..a7ac6e51cf 100644 --- a/src/tests/api/test_order_create.py +++ b/src/tests/api/test_order_create.py @@ -3400,6 +3400,7 @@ def test_order_create_use_gift_cards_only_pending(token_client, organizer, event gc.transactions.create(value=Decimal("100.00"), acceptor=organizer).save() res['status'] = order_status + del res['payment_provider'] res['use_gift_cards'] = [gc.secret] resp = token_client.post( @@ -3430,7 +3431,6 @@ def test_order_create_use_gift_card(token_client, organizer, event, item, quota, res['positions'][0]['answers'][0]['question'] = question.pk with scopes_disabled(): customer = organizer.customers.create() - del res['payment_provider'] res['customer'] = customer.identifier res['api_meta'] = { @@ -3442,7 +3442,7 @@ def test_order_create_use_gift_card(token_client, organizer, event, item, quota, gc = GiftCard.objects.create(issuer=organizer, currency='EUR') gc.transactions.create(value=Decimal("100.00"), acceptor=organizer).save() - + del res['payment_provider'] res['use_gift_cards'] = [gc.secret] djmail.outbox = [] @@ -3519,13 +3519,12 @@ def test_order_create_use_multiple_gift_cards(token_client, organizer, event, it @pytest.mark.django_db -def test_order_create_use_gift_card_and_payment_provider(token_client, organizer, event, item, quota, question): +def test_order_create_use_gift_card_exclusive_with_payment_provider(token_client, organizer, event, item, quota, question): res = copy.deepcopy(ORDER_CREATE_PAYLOAD) res['positions'][0]['item'] = item.pk res['positions'][0]['answers'][0]['question'] = question.pk with scopes_disabled(): customer = organizer.customers.create() - res['customer'] = customer.identifier res['api_meta'] = { 'test': 1 @@ -3536,21 +3535,25 @@ def test_order_create_use_gift_card_and_payment_provider(token_client, organizer res['use_gift_cards'] = [gc.secret] + res_with_payment_provider=copy.deepcopy(res) resp = token_client.post( '/api/v1/organizers/{}/events/{}/orders/'.format( organizer.slug, event.slug - ), format='json', data=res + ), format='json', data=res_with_payment_provider ) - assert resp.status_code == 201 + assert resp.status_code == 400 + assert resp.json() == {"use_gift_cards":["The attribute use_gift_cards is not compatible with payment_provider or payment_info"]} - with scopes_disabled(): - o = Order.objects.get(code=resp.data['code']) - assert o.status == Order.STATUS_PENDING - - open_payment = o.payments.last() - assert open_payment.state == OrderPayment.PAYMENT_STATE_CREATED - assert open_payment.amount == o.total - gc_value - assert open_payment.payment_provider.identifier == res['payment_provider'] + res_with_payment_info = copy.deepcopy(res) + res_with_payment_info['payment_info'] = {"a": "b"} + del res_with_payment_info['payment_provider'] + resp = token_client.post( + '/api/v1/organizers/{}/events/{}/orders/'.format( + organizer.slug, event.slug + ), format='json', data=res_with_payment_info + ) + assert resp.status_code == 400 + assert resp.json() == {"use_gift_cards":["The attribute use_gift_cards is not compatible with payment_provider or payment_info"]} @pytest.mark.django_db