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

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"))

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"))