make payment_provider and use_gift_cards exclusive

This commit is contained in:
Lukas Bockstaller
2026-03-10 17:25:47 +01:00
parent 353a08e094
commit a21e67a9ba
3 changed files with 22 additions and 18 deletions

View File

@@ -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

View File

@@ -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):

View File

@@ -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