mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
API: Writeable methods for vouchers (#639)
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils import timezone
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import Voucher
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -212,3 +216,634 @@ def test_voucher_detail(token_client, organizer, event, voucher, item):
|
||||
voucher.pk))
|
||||
assert resp.status_code == 200
|
||||
assert res == resp.data
|
||||
|
||||
|
||||
def create_voucher(token_client, organizer, event, data, expected_failure=False):
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/vouchers/'.format(organizer.slug, event.slug),
|
||||
data=data, format='json'
|
||||
)
|
||||
if expected_failure:
|
||||
assert resp.status_code == 400
|
||||
else:
|
||||
assert resp.status_code == 201
|
||||
return Voucher.objects.get(pk=resp.data['id'])
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_require_item(token_client, organizer, event, item):
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_create_minimal(token_client, organizer, event, item):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
},
|
||||
)
|
||||
assert v.item == item
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_create_full(token_client, organizer, event, item):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'code': 'ABCDEFGHI',
|
||||
'max_usages': 1,
|
||||
'valid_until': None,
|
||||
'block_quota': False,
|
||||
'allow_ignore_quota': False,
|
||||
'price_mode': 'set',
|
||||
'value': '12.00',
|
||||
'item': item.pk,
|
||||
'variation': None,
|
||||
'quota': None,
|
||||
'tag': 'Foo',
|
||||
'comment': '',
|
||||
'subevent': None
|
||||
},
|
||||
)
|
||||
|
||||
assert v.code == 'ABCDEFGHI'
|
||||
assert v.max_usages == 1
|
||||
assert v.redeemed == 0
|
||||
assert v.valid_until is None
|
||||
assert v.max_usages == 1
|
||||
assert v.block_quota is False
|
||||
assert v.price_mode == 'set'
|
||||
assert v.value == Decimal('12.00')
|
||||
assert v.item == item
|
||||
assert v.variation is None
|
||||
assert v.quota is None
|
||||
assert v.tag == 'Foo'
|
||||
assert v.subevent is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_create_for_addon_item(token_client, organizer, event, item):
|
||||
c = event.categories.create(name="Foo", is_addon=True)
|
||||
item.category = c
|
||||
item.save()
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
}, expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_non_blocking_item_voucher(token_client, organizer, event, item):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
}
|
||||
)
|
||||
assert v.item == item
|
||||
assert v.variation is None
|
||||
assert v.quota is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_non_blocking_variation_voucher(token_client, organizer, event, item):
|
||||
variation = item.variations.create(value="XL")
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'variation': variation.pk
|
||||
}
|
||||
)
|
||||
assert v.item == variation.item
|
||||
assert v.variation == variation
|
||||
assert v.quota is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_non_blocking_quota_voucher(token_client, organizer, event, quota):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'quota': quota.pk
|
||||
}
|
||||
)
|
||||
assert not v.block_quota
|
||||
assert v.quota == quota
|
||||
assert v.item is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_item_voucher_quota_free(token_client, organizer, event, item, quota):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True
|
||||
}
|
||||
)
|
||||
assert v.block_quota
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_item_voucher_quota_full(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_item_voucher_quota_full_invalid(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True,
|
||||
'valid_until': (now() - datetime.timedelta(days=3)).isoformat()
|
||||
}
|
||||
)
|
||||
assert v.block_quota
|
||||
assert not v.is_active()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_variation_voucher_quota_free(token_client, organizer, event, item, quota):
|
||||
variation = item.variations.create(value="XL")
|
||||
quota.variations.add(variation)
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'variation': variation.pk,
|
||||
'block_quota': True
|
||||
}
|
||||
)
|
||||
assert v.block_quota
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_short_code(token_client, organizer, event, item):
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'code': 'ABC',
|
||||
'item': item.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_variation_voucher_quota_full(token_client, organizer, event, item, quota):
|
||||
variation = item.variations.create(value="XL")
|
||||
quota.variations.add(variation)
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'variation': variation.pk,
|
||||
'block_quota': True
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_quota_voucher_quota_free(token_client, organizer, event, quota):
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'quota': quota.pk,
|
||||
'block_quota': True
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_blocking_quota_voucher_quota_full(token_client, organizer, event, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'quota': quota.pk,
|
||||
'block_quota': True
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_duplicate_code(token_client, organizer, event, quota):
|
||||
v = event.vouchers.create(quota=quota)
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'quota': quota.pk,
|
||||
'code': v.code,
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_optional(token_client, organizer, event, item, subevent):
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
},
|
||||
)
|
||||
assert v.subevent is None
|
||||
assert v.block_quota is False
|
||||
assert v.item == item
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_required_for_blocking(token_client, organizer, event, item, subevent):
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_blocking_quota_free(token_client, organizer, event, item, quota, subevent):
|
||||
se2 = event.subevents.create(name="Bar", date_from=now())
|
||||
quota.subevent = subevent
|
||||
quota.save()
|
||||
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
|
||||
q2.items.add(item)
|
||||
|
||||
v = create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True,
|
||||
'subevent': subevent.pk
|
||||
},
|
||||
)
|
||||
assert v.block_quota
|
||||
assert v.subevent == subevent
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_blocking_quota_full(token_client, organizer, event, item, quota, subevent):
|
||||
se2 = event.subevents.create(name="Bar", date_from=now())
|
||||
quota.subevent = subevent
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
|
||||
q2.items.add(item)
|
||||
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={
|
||||
'item': item.pk,
|
||||
'block_quota': True,
|
||||
'subevent': subevent.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
def change_voucher(token_client, organizer, event, voucher, data, expected_failure=False):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/vouchers/{}/'.format(organizer.slug, event.slug, voucher.pk),
|
||||
data=data, format='json'
|
||||
)
|
||||
if expected_failure:
|
||||
assert resp.status_code == 400
|
||||
else:
|
||||
assert resp.status_code == 200
|
||||
voucher.refresh_from_db()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_non_blocking_voucher(token_client, organizer, event, item, quota):
|
||||
v = event.vouchers.create(item=item)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'quota': quota.pk,
|
||||
'item': None
|
||||
}
|
||||
)
|
||||
assert v.item is None
|
||||
assert v.quota == quota
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_voucher_reduce_max_usages(token_client, organizer, event, item, quota):
|
||||
v = event.vouchers.create(item=item, max_usages=5, redeemed=3)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'max_usages': 2
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
assert v.max_usages == 5
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_blocking_voucher_unchanged_quota_full(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
v = event.vouchers.create(item=item, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'comment': 'Foo'
|
||||
}
|
||||
)
|
||||
assert v.item == item
|
||||
assert v.block_quota
|
||||
assert v.comment == 'Foo'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_voucher_to_blocking_quota_full(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
v = event.vouchers.create(item=item)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'block_quota': True
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_voucher_to_blocking_quota_free(token_client, organizer, event, item, quota):
|
||||
v = event.vouchers.create(item=item)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'block_quota': True
|
||||
},
|
||||
)
|
||||
assert v.block_quota
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_voucher_validity_to_valid_quota_full(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
|
||||
block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'valid_until': (now() + datetime.timedelta(days=3)).isoformat()
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
assert v.valid_until < now()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_voucher_validity_to_valid_quota_free(token_client, organizer, event, item, quota):
|
||||
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
|
||||
block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'valid_until': (now() + datetime.timedelta(days=3)).isoformat()
|
||||
},
|
||||
)
|
||||
assert v.valid_until > now()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_item_of_blocking_voucher_quota_free(token_client, organizer, event, item, quota):
|
||||
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
|
||||
quota.items.add(ticket2)
|
||||
v = event.vouchers.create(item=item, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'item': ticket2.pk
|
||||
},
|
||||
)
|
||||
assert v.item == ticket2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_item_of_blocking_voucher_quota_full(token_client, organizer, event, item, quota):
|
||||
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
|
||||
quota2 = event.quotas.create(name='Late', size=0)
|
||||
quota2.items.add(ticket2)
|
||||
v = event.vouchers.create(item=item, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'item': ticket2.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_variation_of_blocking_voucher_quota_free(token_client, organizer, event):
|
||||
shirt = event.items.create(name='Shirt', default_price=23)
|
||||
vs = shirt.variations.create(value='S')
|
||||
vm = shirt.variations.create(value='M')
|
||||
qs = event.quotas.create(name='S', size=2)
|
||||
qs.variations.add(vs)
|
||||
qm = event.quotas.create(name='M', size=2)
|
||||
qm.variations.add(vm)
|
||||
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'variation': vm.pk
|
||||
},
|
||||
)
|
||||
assert v.variation == vm
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_variation_of_blocking_voucher_without_quota_change(token_client, organizer, event):
|
||||
shirt = event.items.create(name='Shirt', default_price=23)
|
||||
vs = shirt.variations.create(value='S')
|
||||
vm = shirt.variations.create(value='M')
|
||||
q = event.quotas.create(name='S', size=0)
|
||||
q.variations.add(vs)
|
||||
q.variations.add(vm)
|
||||
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'variation': vm.pk
|
||||
}
|
||||
)
|
||||
assert v.variation == vm
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_variation_of_blocking_voucher_quota_full(token_client, organizer, event):
|
||||
shirt = event.items.create(name='Shirt', default_price=23)
|
||||
vs = shirt.variations.create(value='S')
|
||||
vm = shirt.variations.create(value='M')
|
||||
qs = event.quotas.create(name='S', size=2)
|
||||
qs.variations.add(vs)
|
||||
qm = event.quotas.create(name='M', size=0)
|
||||
qm.variations.add(vm)
|
||||
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'variation': vm.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_quota_of_blocking_voucher_quota_free(token_client, organizer, event):
|
||||
qs = event.quotas.create(name='S', size=2)
|
||||
qm = event.quotas.create(name='M', size=2)
|
||||
v = event.vouchers.create(quota=qs, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'quota': qm.pk
|
||||
},
|
||||
)
|
||||
assert v.quota == qm
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_quota_of_blocking_voucher_quota_full(token_client, organizer, event):
|
||||
qs = event.quotas.create(name='S', size=2)
|
||||
qm = event.quotas.create(name='M', size=0)
|
||||
v = event.vouchers.create(quota=qs, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'quota': qm.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_item_of_blocking_voucher_without_quota_change(token_client, organizer, event, item, quota):
|
||||
quota.size = 0
|
||||
quota.save()
|
||||
ticket2 = event.items.create(name='Standard Ticket', default_price=23)
|
||||
quota.items.add(ticket2)
|
||||
v = event.vouchers.create(item=item, block_quota=True)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'item': ticket2.pk
|
||||
},
|
||||
)
|
||||
assert v.item == ticket2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_code_to_duplicate(token_client, organizer, event, item, quota):
|
||||
v1 = event.vouchers.create(quota=quota)
|
||||
v2 = event.vouchers.create(quota=quota)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v1,
|
||||
data={
|
||||
'code': v2.code
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_subevent_blocking_quota_free(token_client, organizer, event, item, quota, subevent):
|
||||
quota.subevent = subevent
|
||||
quota.save()
|
||||
se2 = event.subevents.create(name="Bar", date_from=now())
|
||||
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
|
||||
q2.items.add(item)
|
||||
|
||||
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'subevent': se2.pk
|
||||
},
|
||||
)
|
||||
assert v.subevent == se2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_change_subevent_blocking_quota_full(token_client, organizer, event, item, quota, subevent):
|
||||
quota.subevent = subevent
|
||||
quota.save()
|
||||
se2 = event.subevents.create(name="Bar", date_from=now())
|
||||
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
|
||||
q2.items.add(item)
|
||||
|
||||
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'subevent': se2.pk
|
||||
},
|
||||
expected_failure=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_delete_voucher(token_client, organizer, event, quota):
|
||||
v = event.vouchers.create(quota=quota)
|
||||
resp = token_client.delete(
|
||||
'/api/v1/organizers/{}/events/{}/vouchers/{}/'.format(organizer.slug, event.slug, v.pk),
|
||||
)
|
||||
assert resp.status_code == 204
|
||||
assert not event.vouchers.filter(pk=v.id).exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_delete_voucher_redeemed(token_client, organizer, event, quota):
|
||||
v = event.vouchers.create(quota=quota, redeemed=1)
|
||||
resp = token_client.delete(
|
||||
'/api/v1/organizers/{}/events/{}/vouchers/{}/'.format(organizer.slug, event.slug, v.pk),
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
assert event.vouchers.filter(pk=v.id).exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_redeemed_is_not_writable(token_client, organizer, event, item):
|
||||
v = event.vouchers.create(item=item)
|
||||
change_voucher(
|
||||
token_client, organizer, event, v,
|
||||
data={
|
||||
'redeemed': 1,
|
||||
},
|
||||
)
|
||||
assert v.redeemed == 0
|
||||
|
||||
Reference in New Issue
Block a user