mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
- [x] Write operations for subevents - [x] Tests - [x] Documentation
This commit is contained in:
committed by
Raphael Michel
parent
516fab52da
commit
ca7d55082b
@@ -1,4 +1,66 @@
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django_countries.fields import Country
|
||||
from pytz import UTC
|
||||
|
||||
from pretix.base.models import InvoiceAddress, Order, OrderPosition
|
||||
from pretix.base.models.orders import OrderFee
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def variations(item):
|
||||
v = list()
|
||||
v.append(item.variations.create(value="ChildA1", default_price='12.00'))
|
||||
v.append(item.variations.create(value="ChildA2", default_price='13.00'))
|
||||
return v
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def variations2(item2):
|
||||
v = list()
|
||||
v.append(item2.variations.create(value="ChildB1", default_price='12.00'))
|
||||
v.append(item2.variations.create(value="ChildB2", default_price='13.00'))
|
||||
return v
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order(event, item, taxrule):
|
||||
testtime = datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC)
|
||||
|
||||
with mock.patch('django.utils.timezone.now') as mock_now:
|
||||
mock_now.return_value = testtime
|
||||
o = Order.objects.create(
|
||||
code='FOO', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING, secret="k24fiuwvu8kxz3y1",
|
||||
datetime=datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC),
|
||||
expires=datetime(2017, 12, 10, 10, 0, 0, tzinfo=UTC),
|
||||
total=23, locale='en'
|
||||
)
|
||||
o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
|
||||
tax_value=Decimal('0.05'), tax_rule=taxrule)
|
||||
InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ'))
|
||||
return o
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order_position(item, order, subevent, taxrule, variations):
|
||||
op = OrderPosition.objects.create(
|
||||
order=order,
|
||||
item=item,
|
||||
subevent=subevent,
|
||||
variation=variations[0],
|
||||
tax_rule=taxrule,
|
||||
tax_rate=taxrule.rate,
|
||||
tax_value=Decimal("3"),
|
||||
price=Decimal("23"),
|
||||
attendee_name_parts={'full_name': "Peter"},
|
||||
secret="z3fsn8jyufm5kpk768q69gkbyr5f4h6w"
|
||||
)
|
||||
return op
|
||||
|
||||
|
||||
TEST_SUBEVENT_RES = {
|
||||
'active': False,
|
||||
@@ -17,6 +79,16 @@ TEST_SUBEVENT_RES = {
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def item(event):
|
||||
return event.items.create(name="Budget Ticket", default_price=23)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def item2(event2):
|
||||
return event2.items.create(name="Another Ticket", default_price=23)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_list(token_client, organizer, event, subevent):
|
||||
res = dict(TEST_SUBEVENT_RES)
|
||||
@@ -50,6 +122,412 @@ def test_subevent_list(token_client, organizer, event, subevent):
|
||||
assert [] == resp.data['results']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_get(token_client, organizer, event, subevent):
|
||||
res = dict(TEST_SUBEVENT_RES)
|
||||
res["id"] = subevent.pk
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
||||
subevent.pk))
|
||||
assert resp.status_code == 200
|
||||
assert res == resp.data
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_create(token_client, organizer, event, subevent, meta_prop, item):
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
"name": {
|
||||
"de": "Demo Subevent 2020 Test",
|
||||
"en": "Demo Subevent 2020 Test"
|
||||
},
|
||||
"active": False,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": "2017-12-28T10:00:00Z",
|
||||
"date_admission": None,
|
||||
"presale_start": None,
|
||||
"presale_end": None,
|
||||
"location": None,
|
||||
"item_price_overrides": [],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {
|
||||
"type": "Workshop"
|
||||
},
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
assert not subevent.active
|
||||
assert subevent.meta_values.filter(
|
||||
property__name=meta_prop.name, value="Workshop"
|
||||
).exists()
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
"name": {
|
||||
"de": "Demo Subevent 2020 Test",
|
||||
"en": "Demo Subevent 2020 Test"
|
||||
},
|
||||
"active": False,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": "2017-12-28T10:00:00Z",
|
||||
"date_admission": None,
|
||||
"presale_start": None,
|
||||
"presale_end": None,
|
||||
"location": None,
|
||||
"item_price_overrides": [],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {
|
||||
"foo": "bar"
|
||||
},
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"meta_data":["Meta data property \'foo\' does not exist."]}'
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
"name": {
|
||||
"de": "Demo Subevent 2020 Test",
|
||||
"en": "Demo Subevent 2020 Test"
|
||||
},
|
||||
"active": False,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": "2017-12-28T10:00:00Z",
|
||||
"date_admission": None,
|
||||
"presale_start": None,
|
||||
"presale_end": None,
|
||||
"location": None,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item.pk,
|
||||
"price": "23.42"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {
|
||||
"type": "Workshop"
|
||||
},
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
assert item.default_price == Decimal('23.00')
|
||||
assert event.subevents.get(id=resp.data['id']).item_price_overrides[item.pk] == Decimal('23.42')
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
"name": {
|
||||
"de": "Demo Subevent 2020 Test",
|
||||
"en": "Demo Subevent 2020 Test"
|
||||
},
|
||||
"active": False,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": "2017-12-28T10:00:00Z",
|
||||
"date_admission": None,
|
||||
"presale_start": None,
|
||||
"presale_end": None,
|
||||
"location": None,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 555,
|
||||
"price": "23.42"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {
|
||||
"type": "Workshop"
|
||||
},
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"555\\" - object does not exist."]}]}'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_update(token_client, organizer, event, subevent, item, item2, meta_prop, variations, variations2):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"date_from": "2018-12-27T10:00:00Z",
|
||||
"date_to": "2018-12-28T10:00:00Z",
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
subevent = event.subevents.get(id=subevent.id)
|
||||
assert subevent.date_from == datetime(2018, 12, 27, 10, 0, tzinfo=UTC)
|
||||
assert subevent.date_to == datetime(2018, 12, 28, 10, 0, tzinfo=UTC)
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": "2017-12-26T10:00:00Z"
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"non_field_errors":["The event cannot end before it starts."]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"presale_start": "2017-12-27T10:00:00Z",
|
||||
"presale_end": "2017-12-26T10:00:00Z"
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"non_field_errors":["The event\'s presale cannot end before it starts."]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"meta_data": {
|
||||
meta_prop.name: "Conference"
|
||||
}
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert organizer.events.get(slug=event.slug).subevents.get(id=resp.data['id']).meta_values.filter(
|
||||
property__name=meta_prop.name, value="Conference"
|
||||
).exists()
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"meta_data": {
|
||||
}
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert not subevent.meta_values.filter(
|
||||
property__name=meta_prop.name
|
||||
).exists()
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"meta_data": {
|
||||
"test": "test"
|
||||
}
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"meta_data":["Meta data property \'test\' does not exist."]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item.pk,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert subevent.items.get(id=item.pk).default_price == Decimal('23.00')
|
||||
assert subevent.item_price_overrides[item.pk] == Decimal('99.99')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item.pk,
|
||||
"price": "88.88"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('88.88')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item.pk,
|
||||
"price": None
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item.pk,
|
||||
"price": "12.34"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('12.34')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 123,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"123\\" - object does not exist."]}]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": item2.id,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"non_field_errors":["One or more items do not belong to this event."]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": variations[0].pk,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert subevent.variations.get(id=variations[0].pk).default_price == Decimal('12.00')
|
||||
assert subevent.var_price_overrides[variations[0].pk] == Decimal('99.99')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": variations[0].pk,
|
||||
"price": "88.88"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('88.88')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": variations[0].pk,
|
||||
"price": None
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": variations[0].pk,
|
||||
"price": "12.34"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('12.34')
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": 123,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"variation_price_overrides":[{"variation":["Invalid pk \\"123\\" - object does not exist."]}]}'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
{
|
||||
"variation_price_overrides": [
|
||||
{
|
||||
"variation": variations2[0].pk,
|
||||
"price": "99.99"
|
||||
}
|
||||
],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"non_field_errors":["One or more variations do not belong to this event."]}'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_detail(token_client, organizer, event, subevent):
|
||||
res = dict(TEST_SUBEVENT_RES)
|
||||
@@ -58,3 +536,21 @@ def test_subevent_detail(token_client, organizer, event, subevent):
|
||||
subevent.pk))
|
||||
assert resp.status_code == 200
|
||||
assert res == resp.data
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_delete(token_client, organizer, event, subevent):
|
||||
resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
||||
subevent.pk))
|
||||
assert resp.status_code == 204
|
||||
assert not event.subevents.filter(pk=subevent.id).exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_subevent_with_order_position_not_delete(token_client, organizer, event, subevent, item, order_position):
|
||||
resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
||||
subevent.pk))
|
||||
assert resp.status_code == 403
|
||||
assert resp.content.decode() == '{"detail":"The sub-event can not be deleted as it has already been used in ' \
|
||||
'orders. Please set \'active\' to false instead to hide it from users."}'
|
||||
assert event.subevents.filter(pk=subevent.id).exists()
|
||||
|
||||
Reference in New Issue
Block a user