Fix #515 -- Add check-in lists (#693)

* Data model and migration

* Some backwards compatibility

* CRUD for checkin lists

* Show and perform checkins

* Correct numbers in table and dashboard widget

* event creation and cloning

* Allow to link specific exports and pass options per query

* Play with the CSV export

* PDF export

* Collapse exports by default

* Improve PDF exporter

* Addon stuff

* Subevent stuff, pretixdroid tests

* pretixdroid tests

* Add CRUD API

* Test compatibility

* Fix test

* DB-independent sorting behavior

* Add CRUD and coyp tests

* Re-enable pretixdroid plugin

* pretixdroid config

* Tests & fixes
This commit is contained in:
Raphael Michel
2017-12-04 18:12:23 +01:00
committed by GitHub
parent f1be7ed69d
commit 353dce789d
58 changed files with 2402 additions and 608 deletions
+168
View File
@@ -0,0 +1,168 @@
import pytest
from pretix.base.models import CheckinList
@pytest.fixture
def item(event):
return event.items.create(name="Budget Ticket", default_price=23)
@pytest.fixture
def item_on_wrong_event(event2):
return event2.items.create(name="Budget Ticket", default_price=23)
@pytest.fixture
def other_item(event):
return event.items.create(name="Budget Ticket", default_price=23)
TEST_LIST_RES = {
"name": "Default",
"all_products": False,
"limit_products": [],
"position_count": 0,
"checkin_count": 0,
"subevent": None
}
@pytest.fixture
def clist(event, item):
c = event.checkin_lists.create(name="Default", all_products=False)
c.limit_products.add(item)
return c
@pytest.mark.django_db
def test_list_list(token_client, organizer, event, clist, item, subevent):
res = dict(TEST_LIST_RES)
res["id"] = clist.pk
res["limit_products"] = [item.pk]
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert [res] == resp.data['results']
clist.subevent = subevent
clist.save()
res["subevent"] = subevent.pk
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/checkinlists/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
assert [res] == resp.data['results']
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/checkinlists/?subevent={}'.format(organizer.slug, event.slug, subevent.pk + 1))
assert [] == resp.data['results']
@pytest.mark.django_db
def test_list_detail(token_client, organizer, event, clist, item):
res = dict(TEST_LIST_RES)
res["id"] = clist.pk
res["limit_products"] = [item.pk]
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/'.format(organizer.slug, event.slug,
clist.pk))
assert resp.status_code == 200
assert res == resp.data
@pytest.mark.django_db
def test_list_create(token_client, organizer, event, item, item_on_wrong_event):
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [item.pk],
"all_products": False,
"subevent": None
},
format='json'
)
assert resp.status_code == 201
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
assert cl.limit_products.count() == 1
assert not cl.all_products
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [item_on_wrong_event.pk],
"all_products": True,
"subevent": None
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["One or more items do not belong to this event."]}'
@pytest.mark.django_db
def test_list_create_with_subevent(token_client, organizer, event, event3, item, subevent, subevent2):
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [item.pk],
"all_products": True,
"subevent": subevent.pk
},
format='json'
)
assert resp.status_code == 201
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [item.pk],
"all_products": True,
"subevent": None
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["Subevent cannot be null for event series."]}'
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [],
"all_products": True,
"subevent": subevent2.pk
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["The subevent does not belong to this event."]}'
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event3.slug),
{
"name": "VIP",
"limit_products": [],
"all_products": True,
"subevent": subevent2.pk
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["The subevent does not belong to this event."]}'
@pytest.mark.django_db
def test_list_update(token_client, organizer, event, clist):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/checkinlists/{}/'.format(organizer.slug, event.slug, clist.pk),
{
"name": "VIP",
},
format='json'
)
assert resp.status_code == 200
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
+2 -1
View File
@@ -247,7 +247,8 @@ def test_orderposition_list(token_client, organizer, event, order, item, subeven
'/api/v1/organizers/{}/events/{}/orderpositions/?has_checkin=true'.format(organizer.slug, event.slug))
assert [] == resp.data['results']
op.checkins.create(datetime=datetime.datetime(2017, 12, 26, 10, 0, 0, tzinfo=UTC))
cl = event.checkin_lists.create(name="Default")
op.checkins.create(datetime=datetime.datetime(2017, 12, 26, 10, 0, 0, tzinfo=UTC), list=cl)
res['checkins'] = [{'datetime': '2017-12-26T10:00:00Z'}]
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/orderpositions/?has_checkin=true'.format(organizer.slug, event.slug))
+6
View File
@@ -17,6 +17,7 @@ event_urls = [
'subevents/',
'taxrules/',
'waitinglistentries/',
'checkinlists/',
]
event_permission_urls = [
@@ -46,6 +47,11 @@ event_permission_urls = [
('post', 'can_change_orders', 'orders/ABC12/mark_expired/', 404),
('post', 'can_change_orders', 'orders/ABC12/mark_canceled/', 404),
('post', 'can_change_orders', 'orders/ABC12/extend/', 400),
('get', 'can_view_orders', 'checkinlists/', 200),
('post', 'can_change_event_settings', 'checkinlists/', 400),
('put', 'can_change_event_settings', 'checkinlists/1/', 404),
('patch', 'can_change_event_settings', 'checkinlists/1/', 404),
('delete', 'can_change_event_settings', 'checkinlists/1/', 404),
]
+5 -1
View File
@@ -983,6 +983,8 @@ class EventTest(TestCase):
que1.items.add(i1)
event1.settings.foo_setting = 23
event1.settings.tax_rate_default = tr7
cl1 = event1.checkin_lists.create(name="All", all_products=False)
cl1.limit_products.add(i1)
event2 = Event.objects.create(
organizer=self.organizer, name='Download', slug='ab1234',
@@ -990,7 +992,7 @@ class EventTest(TestCase):
)
event2.copy_data_from(event1)
for a in (tr7, c1, c2, i1, q1, que1):
for a in (tr7, c1, c2, i1, q1, que1, cl1):
a.refresh_from_db()
assert a.event == event1
@@ -1012,6 +1014,8 @@ class EventTest(TestCase):
assert que1new.items.get(pk=i1new.pk)
assert event2.settings.foo_setting == '23'
assert event2.settings.tax_rate_default == trnew
assert event2.checkin_lists.count() == 1
assert [i.pk for i in event2.checkin_lists.first().limit_products.all()] == [i1new.pk]
class SubEventTest(TestCase):
+78 -52
View File
@@ -1,4 +1,4 @@
from datetime import timedelta
from datetime import datetime, timedelta, timezone
from decimal import Decimal
import pytest
@@ -10,6 +10,8 @@ from pretix.base.models import (
)
from pretix.control.views.dashboards import checkin_widget
from ..base import SoupTest, extract_form_fields
@pytest.fixture
def dashboard_env():
@@ -27,6 +29,8 @@ def dashboard_env():
t.members.add(user)
t.limit_events.add(event)
cl = event.checkin_lists.create(name="Default", all_products=True)
event.settings.set('attendee_names_asked', True)
event.settings.set('locales', ['en', 'de'])
@@ -50,7 +54,7 @@ def dashboard_env():
price=Decimal("10")
)
return event, user, o, order_paid, item_ticket, item_mascot
return event, user, o, order_paid, item_ticket, item_mascot, cl
@pytest.mark.django_db
@@ -84,32 +88,11 @@ def test_dashboard_with_checkin(dashboard_env):
order=dashboard_env[3],
item=dashboard_env[4]
)
Checkin.objects.create(position=op)
Checkin.objects.create(position=op, list=dashboard_env[6])
c = checkin_widget(dashboard_env[0])
assert '1/2' in c[0]['content']
@pytest.mark.django_db
def test_dashboard_exclude_non_admission_item(dashboard_env):
dashboard_env[0].settings.ticket_download_nonadm = False
dashboard_env[0].save()
c = checkin_widget(dashboard_env[0])
assert '0/1' in c[0]['content']
@pytest.mark.django_db
def test_dashboard_exclude_non_admission_item_with_checkin(dashboard_env):
dashboard_env[0].settings.ticket_download_nonadm = False
dashboard_env[0].save()
op = OrderPosition.objects.get(
order=dashboard_env[3],
item=dashboard_env[4]
)
Checkin.objects.create(position=op)
c = checkin_widget(dashboard_env[0])
assert '1/1' in c[0]['content']
@pytest.fixture
def checkin_list_env():
# permission
@@ -128,9 +111,11 @@ def checkin_list_env():
event.settings.set('locales', ['en', 'de'])
team.limit_events.add(event)
cl = event.checkin_lists.create(name="Default", all_products=True)
# item
item_ticket = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True)
item_mascot = Item.objects.create(event=event, name="Mascot", default_price=10, admission=False)
item_ticket = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True, position=0)
item_mascot = Item.objects.create(event=event, name="Mascot", default_price=10, admission=False, position=1)
# order
order_pending = Order.objects.create(
@@ -196,32 +181,32 @@ def checkin_list_env():
)
# checkin
Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1))
Checkin.objects.create(position=op_a3_ticket)
Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1), list=cl)
Checkin.objects.create(position=op_a3_ticket, list=cl)
return event, user, orga, [item_ticket, item_mascot], [order_pending, order_a1, order_a2, order_a3], \
[op_pending_ticket, op_a1_ticket, op_a1_mascot, op_a2_ticket, op_a3_ticket]
[op_pending_ticket, op_a1_ticket, op_a1_mascot, op_a2_ticket, op_a3_ticket], cl
@pytest.mark.django_db
@pytest.mark.parametrize("order_key, expected", [
('', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
('-code', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
('code', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
('code', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']),
('-email', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
('email', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
('-status', ['A3Ticket', 'A1Ticket', 'A1Mascot', 'A2Ticket']),
('email', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']),
('-status', ['A3Ticket', 'A1Ticket', 'A2Ticket', 'A1Mascot']),
('status', ['A1Mascot', 'A2Ticket', 'A1Ticket', 'A3Ticket']),
('-timestamp', ['A1Ticket', 'A3Ticket', 'A1Mascot', 'A2Ticket']), # A1 checkin date > A3 checkin date
('-timestamp', ['A1Ticket', 'A3Ticket', 'A2Ticket', 'A1Mascot']), # A1 checkin date > A3 checkin date
('timestamp', ['A1Mascot', 'A2Ticket', 'A3Ticket', 'A1Ticket']),
('-name', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
('name', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']), # mascot doesn't include attendee name
('-item', ['A1Ticket', 'A2Ticket', 'A3Ticket', 'A1Mascot']),
('-item', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
('item', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']),
])
def test_checkins_list_ordering(client, checkin_list_env, order_key, expected):
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/checkins/?ordering=' + order_key)
response = client.get('/control/event/dummy/dummy/checkinlists/{}/?ordering='.format(checkin_list_env[6].pk) + order_key)
qs = response.context['entries']
item_keys = [q.order.code + str(q.item.name) for q in qs]
assert item_keys == expected
@@ -240,7 +225,7 @@ def test_checkins_list_ordering(client, checkin_list_env, order_key, expected):
])
def test_checkins_list_filter(client, checkin_list_env, query, expected):
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/checkins/?' + query)
response = client.get('/control/event/dummy/dummy/checkinlists/{}/?'.format(checkin_list_env[6].pk) + query)
qs = response.context['entries']
item_keys = [q.order.code + str(q.item.name) for q in qs]
print([str(item.name) + '-' + str(item.id) for item in Item.objects.all()])
@@ -251,7 +236,7 @@ def test_checkins_list_filter(client, checkin_list_env, query, expected):
def test_checkins_item_filter(client, checkin_list_env):
client.login(email='dummy@dummy.dummy', password='dummy')
for item in checkin_list_env[3]:
response = client.get('/control/event/dummy/dummy/checkins/?item=' + str(item.id))
response = client.get('/control/event/dummy/dummy/checkinlists/{}/?item={}'.format(checkin_list_env[6].pk, item.pk))
assert all(i.item.id == item.id for i in response.context['entries'])
@@ -263,7 +248,7 @@ def test_checkins_item_filter(client, checkin_list_env):
])
def test_checkins_list_mixed(client, checkin_list_env, query, expected):
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/checkins/?' + query)
response = client.get('/control/event/dummy/dummy/checkinlists/{}/?{}'.format(checkin_list_env[6].pk, query))
qs = response.context['entries']
item_keys = [q.order.code + str(q.item.name) for q in qs]
assert item_keys == expected
@@ -273,7 +258,7 @@ def test_checkins_list_mixed(client, checkin_list_env, query, expected):
def test_manual_checkins(client, checkin_list_env):
client.login(email='dummy@dummy.dummy', password='dummy')
assert not checkin_list_env[5][3].checkins.exists()
client.post('/control/event/dummy/dummy/checkins/', {
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
'checkin': [checkin_list_env[5][3].pk]
})
assert checkin_list_env[5][3].checkins.exists()
@@ -299,6 +284,7 @@ def checkin_list_with_addon_env():
event.settings.set('attendee_names_asked', True)
event.settings.set('locales', ['en', 'de'])
team.limit_events.add(event)
cl = event.checkin_lists.create(name="Default", all_products=True)
# item
cat_adm = ItemCategory.objects.create(event=event, name="Admission")
@@ -359,29 +345,69 @@ def checkin_list_with_addon_env():
)
# checkin
Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1))
Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1), list=cl)
return event, user, orga, [item_ticket, item_workshop], [order_pending, order_a1, order_a2], \
[op_pending_ticket, op_a1_ticket, op_a1_workshop, op_a2_ticket]
[op_pending_ticket, op_a1_ticket, op_a1_workshop, op_a2_ticket], cl
@pytest.mark.django_db
def test_checkins_attendee_name_from_addon_available(client, checkin_list_with_addon_env):
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/checkins/')
response = client.get('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_with_addon_env[6].pk))
qs = response.context['entries']
item_keys = [q.order.code + str(q.item.name) +
(str(q.addon_to.attendee_name) if q.addon_to is not None else str(q.attendee_name)) for q in qs]
assert item_keys == ['A1TicketA1', 'A1WorkshopA1', 'A2TicketA2'] # A1Workshop<name> comes from addon_to position
@pytest.mark.django_db
def test_checkins_with_noadm_option(client, checkin_list_with_addon_env):
checkin_list_with_addon_env[0].settings.ticket_download_nonadm = False
checkin_list_with_addon_env[0].save()
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/checkins/')
qs = response.context['entries']
item_keys = [q.order.code + str(q.item.name) +
(str(q.addon_to.attendee_name) if q.addon_to is not None else str(q.attendee_name)) for q in qs]
assert item_keys == ['A1TicketA1', 'A2TicketA2']
class CheckinListFormTest(SoupTest):
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
self.orga1 = Organizer.objects.create(name='CCC', slug='ccc')
self.orga2 = Organizer.objects.create(name='MRM', slug='mrm')
self.event1 = Event.objects.create(
organizer=self.orga1, name='30C3', slug='30c3',
date_from=datetime(2013, 12, 26, tzinfo=timezone.utc),
)
t = Team.objects.create(organizer=self.orga1, can_change_event_settings=True, can_view_orders=True)
t.members.add(self.user)
t.limit_events.add(self.event1)
self.client.login(email='dummy@dummy.dummy', password='dummy')
self.item_ticket = Item.objects.create(event=self.event1, name="Ticket", default_price=23, admission=True)
def test_create(self):
doc = self.get_doc('/control/event/%s/%s/checkinlists/add' % (self.orga1.slug, self.event1.slug))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['name'] = 'All'
form_data['all_products'] = 'on'
doc = self.post_doc('/control/event/%s/%s/checkinlists/add' % (self.orga1.slug, self.event1.slug), form_data)
assert doc.select(".alert-success")
self.assertIn("All", doc.select("#page-wrapper table")[0].text)
assert self.event1.checkin_lists.get(
name='All', all_products=True
)
def test_update(self):
cl = self.event1.checkin_lists.create(name='All', all_products=True)
doc = self.get_doc('/control/event/%s/%s/checkinlists/%s/change' % (self.orga1.slug, self.event1.slug, cl.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['all_products'] = ''
form_data['limit_products'] = str(self.item_ticket.pk)
doc = self.post_doc('/control/event/%s/%s/checkinlists/%s/change' % (self.orga1.slug, self.event1.slug, cl.id),
form_data)
assert doc.select(".alert-success")
cl.refresh_from_db()
assert not cl.all_products
assert list(cl.limit_products.all()) == [self.item_ticket]
def test_delete(self):
cl = self.event1.checkin_lists.create(name='All', all_products=True)
doc = self.get_doc('/control/event/%s/%s/checkinlists/%s/delete' % (self.orga1.slug, self.event1.slug, cl.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
doc = self.post_doc('/control/event/%s/%s/checkinlists/%s/delete' % (self.orga1.slug, self.event1.slug, cl.id),
form_data)
assert doc.select(".alert-success")
self.assertNotIn("VAT", doc.select("#page-wrapper")[0].text)
assert not self.event1.checkin_lists.exists()
+15
View File
@@ -613,6 +613,12 @@ class SubEventsTest(SoupTest):
'location_0': 'Hamburg',
'presale_start_0': '2017-06-20',
'presale_start_1': '10:00:00',
'checkinlist_set-TOTAL_FORMS': '1',
'checkinlist_set-INITIAL_FORMS': '0',
'checkinlist_set-MIN_NUM_FORMS': '0',
'checkinlist_set-MAX_NUM_FORMS': '1000',
'checkinlist_set-0-name': 'Default',
'checkinlist_set-0-all_products': 'on',
'quotas-TOTAL_FORMS': '1',
'quotas-INITIAL_FORMS': '0',
'quotas-MIN_NUM_FORMS': '0',
@@ -638,6 +644,7 @@ class SubEventsTest(SoupTest):
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
def test_modify(self):
doc = self.get_doc('/control/event/ccc/30c3/subevents/%d/' % self.subevent1.pk)
@@ -659,8 +666,15 @@ class SubEventsTest(SoupTest):
'quotas-0-name': 'Q1',
'quotas-0-size': '50',
'quotas-0-itemvars': str(self.ticket.pk),
'checkinlist_set-TOTAL_FORMS': '1',
'checkinlist_set-INITIAL_FORMS': '0',
'checkinlist_set-MIN_NUM_FORMS': '0',
'checkinlist_set-MAX_NUM_FORMS': '1000',
'checkinlist_set-0-name': 'Default',
'checkinlist_set-0-all_products': 'on',
'item-%d-price' % self.ticket.pk: '12'
})
print(doc)
assert doc.select(".alert-success")
self.subevent1.refresh_from_db()
se = self.subevent1
@@ -678,6 +692,7 @@ class SubEventsTest(SoupTest):
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
def test_delete(self):
doc = self.get_doc('/control/event/ccc/30c3/subevents/%d/delete' % self.subevent1.pk)
+9 -1
View File
@@ -89,6 +89,10 @@ event_urls = [
"orders/ABC/checkvatid",
"orders/ABC/",
"orders/",
"checkinlists/",
"checkinlists/1/",
"checkinlists/1/change",
"checkinlists/1/delete",
"waitinglist/",
"waitinglist/auto_assign",
"invoice/1",
@@ -225,7 +229,11 @@ event_permission_urls = [
("can_change_vouchers", "vouchers/1234/delete", 404),
("can_view_orders", "waitinglist/", 200),
("can_change_orders", "waitinglist/auto_assign", 405),
("can_view_orders", "checkins/", 200),
("can_view_orders", "checkinlists/", 200),
("can_view_orders", "checkinlists/1/", 404),
("can_change_event_settings", "checkinlists/add", 200),
("can_change_event_settings", "checkinlists/1/change", 404),
("can_change_event_settings", "checkinlists/1/delete", 404),
]
+85 -15
View File
@@ -42,12 +42,14 @@ def env():
order=o1, item=ticket,
price=23, attendee_name="Peter", secret='5678910'
)
return event, user, o1, op1, op2
cl1 = event.checkin_lists.create(name="Foo", all_products=True)
cl2 = event.checkin_lists.create(name="Bar", all_products=True)
return event, user, o1, op1, op2, cl1, cl2
@pytest.mark.django_db
def test_custom_datetime(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
dt = now() - timedelta(days=1)
dt = dt.replace(microsecond=0)
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
@@ -60,7 +62,7 @@ def test_custom_datetime(client, env):
@pytest.mark.django_db
def test_only_once(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '1234'})
@@ -76,7 +78,7 @@ def test_only_once(client, env):
@pytest.mark.django_db
def test_item_scope(client, env):
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=False)
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=False, list=env[5])
ac.items.add(env[4].item)
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
@@ -91,9 +93,28 @@ def test_item_scope(client, env):
assert jdata['reason'] == 'product'
@pytest.mark.django_db
def test_item_restricted_list(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=True, list=env[5])
env[5].all_products = False
env[5].limit_products.add(env[4].item)
env[5].save()
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': env[4].secret})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['version'] == API_VERSION
assert jdata['status'] == 'ok'
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': env[3].secret})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['status'] == 'error'
assert jdata['reason'] == 'product'
@pytest.mark.django_db
def test_reupload_same_nonce(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '1234', 'nonce': 'fooobar'})
@@ -107,9 +128,27 @@ def test_reupload_same_nonce(client, env):
assert Checkin.objects.count() == 1
@pytest.mark.django_db
def test_multiple_different_list(client, env):
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '1234'})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['version'] == API_VERSION
assert jdata['status'] == 'ok'
ac.list = env[6]
ac.save()
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '1234'})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['status'] == 'ok'
@pytest.mark.django_db
def test_forced_multiple(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '1234'})
@@ -124,7 +163,7 @@ def test_forced_multiple(client, env):
@pytest.mark.django_db
def test_require_paid(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
env[2].status = Order.STATUS_PENDING
env[2].save()
@@ -137,7 +176,7 @@ def test_require_paid(client, env):
@pytest.mark.django_db
def test_unknown(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
data={'secret': '4321'})
@@ -162,7 +201,7 @@ def test_unknown_event(client, env):
@pytest.mark.django_db
def test_search(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg', '567891'))
jdata = json.loads(resp.content.decode("utf-8"))
@@ -175,9 +214,28 @@ def test_search(client, env):
assert jdata['results'][0]['secret'] == '5678910'
@pytest.mark.django_db
def test_search_item_restricted_list(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
env[5].all_products = False
env[5].limit_products.add(env[4].item)
env[5].save()
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg', '567891'))
jdata = json.loads(resp.content.decode("utf-8"))
assert len(jdata['results']) == 1
assert jdata['results'][0]['secret'] == env[4].secret
env[5].limit_products.remove(env[4].item)
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg', '567891'))
jdata = json.loads(resp.content.decode("utf-8"))
assert len(jdata['results']) == 0
@pytest.mark.django_db
def test_search_restricted(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', allow_search=False)
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5], allow_search=False)
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg', '567891'))
jdata = json.loads(resp.content.decode("utf-8"))
@@ -191,7 +249,7 @@ def test_search_restricted(client, env):
@pytest.mark.django_db
def test_search_invoice_name(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
InvoiceAddress.objects.create(order=env[2], name="John")
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg', 'John'))
@@ -202,7 +260,7 @@ def test_search_invoice_name(client, env):
@pytest.mark.django_db
def test_download_all_data(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
resp = client.get('/pretixdroid/api/%s/%s/download/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))
assert len(jdata['results']) == 2
@@ -212,7 +270,7 @@ def test_download_all_data(client, env):
@pytest.mark.django_db
def test_download_item_restriction(client, env):
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=False)
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5], all_items=False)
ac.items.add(env[4].item)
resp = client.get('/pretixdroid/api/%s/%s/download/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))
@@ -220,10 +278,22 @@ def test_download_item_restriction(client, env):
assert jdata['results'][0]['secret'] == env[4].secret
@pytest.mark.django_db
def test_download_item_restricted_list(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=True, list=env[5])
env[5].all_products = False
env[5].limit_products.add(env[4].item)
env[5].save()
resp = client.get('/pretixdroid/api/%s/%s/download/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))
assert len(jdata['results']) == 1
assert jdata['results'][0]['secret'] == env[4].secret
@pytest.mark.django_db
def test_status(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
Checkin.objects.create(position=env[3])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[5])
Checkin.objects.create(position=env[3], list=env[5])
resp = client.get('/pretixdroid/api/%s/%s/status/?key=%s' % (
env[0].organizer.slug, env[0].slug, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))
+18 -20
View File
@@ -45,12 +45,14 @@ def env():
order=o1, item=ticket,
price=23, attendee_name="Peter", secret='5678910', subevent=se2
)
return event, user, o1, op1, op2, se1, se2
cl1 = event.checkin_lists.create(name="Foo", all_products=True, subevent=se1)
cl2 = event.checkin_lists.create(name="Foo", all_products=True, subevent=se2)
return event, user, o1, op1, op2, se1, se2, cl1, cl2
@pytest.mark.django_db
def test_custom_datetime(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[7])
dt = now() - timedelta(days=1)
dt = dt.replace(microsecond=0)
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
@@ -64,14 +66,12 @@ def test_custom_datetime(client, env):
@pytest.mark.django_db
def test_wrong_subevent(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[8])
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg'
), data={'secret': '5678910'})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['status'] == 'error'
assert jdata['reason'] == 'unknown_ticket'
assert resp.status_code == 403
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[6].pk, 'abcdefg'
@@ -82,17 +82,14 @@ def test_wrong_subevent(client, env):
@pytest.mark.django_db
def test_other_subevent_not_allowed(client, env):
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[7])
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[6].pk, 'abcdefg'
), data={'secret': '5678910'})
jdata = json.loads(resp.content.decode("utf-8"))
assert jdata['status'] == 'error'
assert jdata['reason'] == 'unknown_ticket'
assert resp.status_code == 403
ac.subevent = env[6]
ac.save()
env[7].subevent = env[6]
env[7].save()
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[6].pk, 'abcdefg'
@@ -103,11 +100,11 @@ def test_other_subevent_not_allowed(client, env):
@pytest.mark.django_db
def test_unknown_subevent(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[7])
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[6].pk + 1000, 'abcdefg'
), data={'secret': '5678910'})
assert resp.status_code == 404
assert resp.status_code == 403
@pytest.mark.django_db
@@ -120,9 +117,10 @@ def test_no_subevent(client, env):
@pytest.mark.django_db
def test_search(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg')
AppConfiguration.objects.create(event=env[0], key='hijklmn', list=env[7])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[8])
resp = client.get('/pretixdroid/api/%s/%s/%d/search/?key=%s&query=%s' % (
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg', '567891'))
env[0].organizer.slug, env[0].slug, env[5].pk, 'hijklmn', '567891'))
jdata = json.loads(resp.content.decode("utf-8"))
assert len(jdata['results']) == 0
resp = client.get('/pretixdroid/api/%s/%s/%d/search/?key=%s&query=%s' % (
@@ -134,7 +132,7 @@ def test_search(client, env):
@pytest.mark.django_db
def test_download_all_data(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[7])
resp = client.get('/pretixdroid/api/%s/%s/%d/download/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))
@@ -144,8 +142,8 @@ def test_download_all_data(client, env):
@pytest.mark.django_db
def test_status(client, env):
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
Checkin.objects.create(position=env[3])
AppConfiguration.objects.create(event=env[0], key='abcdefg', list=env[7])
Checkin.objects.create(position=env[3], list=env[7])
resp = client.get('/pretixdroid/api/%s/%s/%d/status/?key=%s' % (
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg'))
jdata = json.loads(resp.content.decode("utf-8"))