Files
pretix_cgo/src/tests/api/test_subevents.py
Raphael Michel fb403dad88 Add comment field to subevents (Z#23148472) (#4099)
* Add comment field to subevents (Z#23148472)

* Review fix
2024-04-22 12:56:29 +02:00

1018 lines
35 KiB
Python

#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from datetime import datetime, timezone
from decimal import Decimal
from unittest import mock
import pytest
from django_countries.fields import Country
from django_scopes import scopes_disabled
from pretix.base.models import (
InvoiceAddress, Order, OrderPosition, SeatingPlan, SubEvent,
)
from pretix.base.models.orders import OrderFee
@pytest.fixture
def variations(item):
v = []
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 = []
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=timezone.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=timezone.utc),
expires=datetime(2017, 12, 10, 10, 0, 0, tzinfo=timezone.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,
'event': 'dummy',
'presale_start': None,
'date_to': None,
'date_admission': None,
'name': {'en': 'Foobar'},
'frontpage_text': None,
'date_from': '2017-12-27T10:00:00Z',
'presale_end': None,
'seating_plan': None,
"seat_category_mapping": {},
'id': 1,
'variation_price_overrides': [],
'location': None,
"geo_lat": None,
"geo_lon": None,
'is_public': True,
'item_price_overrides': [],
'comment': None,
'meta_data': {'type': 'Workshop'}
}
@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)
res["id"] = subevent.pk
res["last_modified"] = subevent.last_modified.isoformat().replace('+00:00', 'Z')
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert [res] == resp.data['results']
resp = token_client.get('/api/v1/organizers/{}/subevents/'.format(organizer.slug))
assert resp.status_code == 200
assert [res] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?active=false'.format(organizer.slug, event.slug))
assert [res] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?active=true'.format(organizer.slug, event.slug))
assert [] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?event__live=false'.format(organizer.slug, event.slug))
assert [res] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?event__live=true'.format(organizer.slug, event.slug))
assert [] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T09:59:59Z'.format(organizer.slug, event.slug))
assert [res] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T10:01:01Z'.format(organizer.slug, event.slug))
assert [] == resp.data['results']
resp = token_client.get('/api/v1/organizers/{}/events/?with_availability_for=web'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['results'][0]['best_availability_state'] is None
@pytest.mark.django_db
def test_subevent_list_filter(token_client, organizer, event, subevent):
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/?attr[type]=Workshop'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/?attr[type]=Conference'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/?search=Foobar'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/?search=Barfoo'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?date_from_after=2017-12-27T10:00:00Z'.format(
organizer.slug, event.slug
)
)
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?date_from_after=2017-12-27T10:00:01Z'.format(
organizer.slug, event.slug
)
)
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?date_from_before=2017-12-27T10:00:00Z'.format(
organizer.slug, event.slug
)
)
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/subevents/?date_from_before=2017-12-27T09:59:00Z'.format(
organizer.slug, event.slug
)
)
assert resp.status_code == 200
assert resp.data['count'] == 0
@pytest.mark.django_db
def test_all_subevents_list_filter(token_client, organizer, event, subevent):
resp = token_client.get('/api/v1/organizers/{}/subevents/?attr[type]=Workshop'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get('/api/v1/organizers/{}/subevents/?attr[type]=Conference'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get('/api/v1/organizers/{}/subevents/?search=Foobar'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get('/api/v1/organizers/{}/subevents/?search=Barfoo'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get('/api/v1/organizers/{}/subevents/?search=dummy'.format(organizer.slug))
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get(
'/api/v1/organizers/{}/subevents/?date_from_after=2017-12-27T10:00:00Z'.format(organizer.slug)
)
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get(
'/api/v1/organizers/{}/subevents/?date_from_after=2017-12-27T10:00:01Z'.format(organizer.slug)
)
assert resp.status_code == 200
assert resp.data['count'] == 0
resp = token_client.get(
'/api/v1/organizers/{}/subevents/?date_from_before=2017-12-27T10:00:00Z'.format(organizer.slug)
)
assert resp.status_code == 200
assert resp.data['count'] == 1
resp = token_client.get(
'/api/v1/organizers/{}/subevents/?date_from_before=2017-12-27T09:59:00Z'.format(organizer.slug)
)
assert resp.status_code == 200
assert resp.data['count'] == 0
@pytest.mark.django_db
def test_subevent_create(team, token_client, organizer, event, subevent, meta_prop, item):
meta_prop.choices = [{"key": "Conference", "label": {"en": "Conference"}}, {"key": "Workshop", "label": {"en": "Workshop"}}]
meta_prop.save()
team.can_change_organizer_settings = False
team.save()
organizer.meta_properties.create(
name="protected", protected=True
)
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",
"protected": "ignored",
},
},
format='json'
)
assert resp.status_code == 201
assert not subevent.active
with scopes_disabled():
assert subevent.meta_values.filter(
property__name=meta_prop.name, value="Workshop"
).exists()
assert not subevent.meta_values.filter(
property__name="ignored",
).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": [],
"variation_price_overrides": [],
"meta_data": {
meta_prop.name: "bar"
},
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"meta_data":["Meta data property \'type\' does not allow value \'bar\'."]}'
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')
with scopes_disabled():
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
with scopes_disabled():
subevent = event.subevents.get(id=subevent.id)
assert subevent.date_from == datetime(2018, 12, 27, 10, 0, tzinfo=timezone.utc)
assert subevent.date_to == datetime(2018, 12, 28, 10, 0, tzinfo=timezone.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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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
with scopes_disabled():
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_update_keep_subeventitems(token_client, organizer, event, subevent, item, item2):
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",
"disabled": True
}
],
},
format='json'
)
assert resp.status_code == 200
with scopes_disabled():
assert event.subevents.get(id=subevent.id).item_overrides[item.pk].disabled
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"date_from": "2017-12-27T10:00:00Z",
},
format='json'
)
assert resp.status_code == 200
with scopes_disabled():
assert event.subevents.get(id=subevent.id).item_overrides[item.pk].disabled
@pytest.mark.django_db
def test_subevent_detail(token_client, organizer, event, subevent):
res = dict(TEST_SUBEVENT_RES)
res["id"] = subevent.pk
res["last_modified"] = subevent.last_modified.isoformat().replace('+00:00', 'Z')
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_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
with scopes_disabled():
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."}'
with scopes_disabled():
assert event.subevents.filter(pk=subevent.id).exists()
@pytest.fixture
def seatingplan(event, organizer, item):
return SeatingPlan.objects.create(
name="Plan", organizer=organizer, layout="""{
"name": "Grosser Saal",
"categories": [
{
"name": "Stalls",
"color": "red"
}
],
"zones": [
{
"name": "Main Area",
"position": {
"x": 0,
"y": 0
},
"rows": [
{
"row_number": "0",
"seats": [
{
"seat_guid": "0-0",
"seat_number": "0-0",
"position": {
"x": 0,
"y": 0
},
"category": "Stalls"
},
{
"seat_guid": "0-1",
"seat_number": "0-1",
"position": {
"x": 33,
"y": 0
},
"category": "Stalls"
},
{
"seat_guid": "0-2",
"seat_number": "0-2",
"position": {
"x": 66,
"y": 0
},
"category": "Stalls"
}
],
"position": {
"x": 0,
"y": 0
}
}
]
}
],
"size": {
"width": 600,
"height": 400
}
}"""
)
@pytest.mark.django_db
def test_subevent_update_seating(token_client, organizer, event, item, subevent, seatingplan):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": seatingplan.pk,
"seat_category_mapping": {
"Stalls": item.pk
}
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan == seatingplan
with scopes_disabled():
assert subevent.seats.count() == 3
assert subevent.seats.filter(product=item).count() == 3
m = subevent.seat_category_mappings.get()
assert m.layout_category == 'Stalls'
assert m.product == item
@pytest.mark.django_db
def test_subevent_update_seating_invalid_product(token_client, organizer, event, item, seatingplan, subevent):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": seatingplan.pk,
"seat_category_mapping": {
"Stalls": item.pk + 2
}
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"seat_category_mapping":["Item \'%d\' does not exist."]}' % (item.pk + 2)
@pytest.mark.django_db
def test_subevent_update_seating_change_mapping(token_client, organizer, event, item, seatingplan, subevent):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": seatingplan.pk,
"seat_category_mapping": {
"Stalls": item.pk
}
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan == seatingplan
with scopes_disabled():
assert subevent.seats.count() == 3
assert subevent.seats.filter(product=item).count() == 3
m = subevent.seat_category_mappings.get()
assert m.layout_category == 'Stalls'
assert m.product == item
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seat_category_mapping": {
"VIP": item.pk,
}
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan == seatingplan
with scopes_disabled():
assert subevent.seats.count() == 3
m = subevent.seat_category_mappings.get()
assert subevent.seats.filter(product=None).count() == 3
assert m.layout_category == 'VIP'
assert m.product == item
@pytest.mark.django_db
def test_remove_seating(token_client, organizer, event, item, seatingplan, subevent):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": seatingplan.pk,
"seat_category_mapping": {
"Stalls": item.pk
}
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan == seatingplan
with scopes_disabled():
assert subevent.seats.count() == 3
assert subevent.seat_category_mappings.count() == 1
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": None
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan is None
with scopes_disabled():
assert subevent.seats.count() == 0
assert subevent.seat_category_mappings.count() == 0
@pytest.mark.django_db
def test_remove_seating_forbidden(token_client, organizer, event, item, seatingplan, order_position, subevent):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": seatingplan.pk,
"seat_category_mapping": {
"Stalls": item.pk
}
},
format='json'
)
assert resp.status_code == 200
subevent.refresh_from_db()
assert subevent.seating_plan == seatingplan
with scopes_disabled():
assert subevent.seats.count() == 3
assert subevent.seat_category_mappings.count() == 1
order_position.seat = subevent.seats.first()
order_position.save()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
{
"seating_plan": None
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"seating_plan":["You can not change the plan since seat \\"0-0\\" is not ' \
'present in the new plan and is already sold."]}'
@pytest.mark.django_db
def test_subevent_create_with_seating(token_client, organizer, event, subevent, item, seatingplan):
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": [],
"seat_category_mapping": {
"Stalls": item.pk
},
"meta_data": {},
"seating_plan": seatingplan.pk,
},
format='json'
)
assert resp.status_code == 201
with scopes_disabled():
subevent = SubEvent.objects.get(pk=resp.data['id'])
assert subevent.seats.count() == 3
assert subevent.seat_category_mappings.count() == 1