forked from CGM_Public/pretix_original
New pretixdroid configuration system
This commit is contained in:
@@ -4,8 +4,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-27 07:30+0000\n"
|
||||
"PO-Revision-Date: 2017-08-27 09:33+0200\n"
|
||||
"POT-Creation-Date: 2017-08-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2017-08-29 23:16+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: Raphael Michel <michel@rami.io>\n"
|
||||
"Language: de\n"
|
||||
@@ -13,7 +13,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.0.3\n"
|
||||
"X-Generator: Poedit 2.0.2\n"
|
||||
"X-Poedit-Bookmarks: -1,-1,904,-1,-1,-1,-1,-1,-1,-1\n"
|
||||
|
||||
#: pretix/base/exporters/answers.py:18
|
||||
@@ -1034,6 +1034,8 @@ msgstr "Antwort"
|
||||
#: pretix/control/templates/pretixcontrol/waitinglist/index.html:119
|
||||
#: pretix/plugins/checkinlists/exporters.py:69
|
||||
#: pretix/plugins/checkinlists/exporters.py:109
|
||||
#: pretix/plugins/pretixdroid/models.py:15
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:46
|
||||
#: pretix/plugins/reports/exporters.py:248
|
||||
msgctxt "subevent"
|
||||
msgid "Date"
|
||||
@@ -1227,6 +1229,8 @@ msgstr "Das Produkt \"{item}\" ist nicht mehr verfügbar."
|
||||
#: pretix/base/models/orders.py:549 pretix/control/views/item.py:436
|
||||
#: pretix/control/views/vouchers.py:81 pretix/control/views/vouchers.py:82
|
||||
#: pretix/plugins/checkinlists/exporters.py:124
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:71
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:72
|
||||
#: pretix/presale/checkoutflow.py:477
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@@ -1236,6 +1240,8 @@ msgstr "Ja"
|
||||
#: pretix/control/views/vouchers.py:82
|
||||
#: pretix/plugins/checkinlists/exporters.py:124
|
||||
#: pretix/plugins/paypal/templates/pretixplugins/paypal/action_refund.html:14
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:71
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:72
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/action_refund.html:14
|
||||
#: pretix/presale/checkoutflow.py:479
|
||||
msgid "No"
|
||||
@@ -3769,6 +3775,8 @@ msgstr "Alle Veranstalter"
|
||||
|
||||
#: pretix/control/forms/filter.py:195
|
||||
#: pretix/control/templates/pretixcontrol/organizers/teams.html:39
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:59
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:63
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
@@ -6063,6 +6071,7 @@ msgid "The following products might be no longer available for sale:"
|
||||
msgstr "Die folgenden Produkte stehen möglicherweise nicht mehr zum Verkauf:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/items/quota_edit.html:27
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:48
|
||||
msgid "Items"
|
||||
msgstr "Produkte"
|
||||
|
||||
@@ -8786,6 +8795,43 @@ msgid ""
|
||||
"This plugin allows you to use the pretixdroid Android app for your event."
|
||||
msgstr "Dieses Plugin erlaubt, die pretixdroid-Android-App zu verwenden."
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:11
|
||||
msgid "Can scan all products"
|
||||
msgstr "Kann alle Produkte scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:12
|
||||
msgid "Can scan these products"
|
||||
msgstr "Nur diese Produkte"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:13
|
||||
msgid "pretixdroid 1.6 or newer only"
|
||||
msgstr "pretixdroid 1.6 oder neuer"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:16
|
||||
msgid "Show information"
|
||||
msgstr "Informationen anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:17
|
||||
msgid ""
|
||||
"If disabled, the device can not see how many tickets exist and how many are "
|
||||
"already scanned. pretixdroid 1.6 or newer only."
|
||||
msgstr ""
|
||||
"Wenn diese Option deaktiviert ist, kann das Gerät nicht sehen wie viele "
|
||||
"Tickets existieren und wie viele bereits gescannt wurden (ab pretixdroid "
|
||||
"1.6)."
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:19
|
||||
msgid "Search allowed"
|
||||
msgstr "Suche erlaubt"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:20
|
||||
msgid ""
|
||||
"If disabled, the device can not search for attendees by name. pretixdroid "
|
||||
"1.6 or newer only."
|
||||
msgstr ""
|
||||
"Wenn diese Option deaktiviert ist, kann mit dem Gerät nicht nach Namen "
|
||||
"gesucht werden (ab pretixdroid 1.6)."
|
||||
|
||||
#: pretix/plugins/pretixdroid/signals.py:21
|
||||
msgid "pretixdroid"
|
||||
msgstr "pretixdroid"
|
||||
@@ -8820,6 +8866,8 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:5
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:7
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:5
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:8
|
||||
msgid "pretixdroid configuration"
|
||||
msgstr "pretixdroid-Konfiguration"
|
||||
|
||||
@@ -8832,45 +8880,76 @@ msgstr ""
|
||||
"die Tickets scannen und überprüfen können."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:11
|
||||
msgid "App download"
|
||||
msgstr "App-Download"
|
||||
msgid "Create app configuration"
|
||||
msgstr "App-Konfiguration erstellen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:15
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:13
|
||||
msgid ""
|
||||
"To start scanning tickets with our Android app, first create a configuration "
|
||||
"code here:"
|
||||
msgstr ""
|
||||
"Um mit unserer Android-App Tickets zu scannen, erstellen Sie hier erst einen "
|
||||
"Konfigurations-Code:"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:30
|
||||
msgid "Create"
|
||||
msgstr "Erstellen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:38
|
||||
msgid "Existing app configurations"
|
||||
msgstr "Bestehende App-Konfigurationen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:44
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:49
|
||||
msgid "Show info"
|
||||
msgstr "Infos anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:50
|
||||
msgid "Allow search"
|
||||
msgstr "Sucher erlauben"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:75
|
||||
msgid "Show QR code"
|
||||
msgstr "QR-Code anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:10
|
||||
msgid "Back to overview"
|
||||
msgstr "Zurück zur Übersicht"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:13
|
||||
msgid "1. Download app"
|
||||
msgstr "1. App herunterladen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:17
|
||||
msgid "Download the app from the Google Play Store"
|
||||
msgstr "Laden Sie die App aus dem Play Store herunter"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:20
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:22
|
||||
msgid ""
|
||||
"Android, Google Play and the Google Play logo are trademarks of Google Inc."
|
||||
msgstr ""
|
||||
"Android, Google Play und das Google Play-Logo sind eingetragene Marken von "
|
||||
"Google Inc."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:25
|
||||
msgid "App configuration"
|
||||
msgstr "App-Konfiguration"
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:27
|
||||
msgid "2. Scan code"
|
||||
msgstr "2. Code scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:27
|
||||
msgid ""
|
||||
"If you start the app for the first time, it will request that you scan the "
|
||||
"following code. The code tells the app all it needs about your event."
|
||||
msgstr ""
|
||||
"Wenn Sie die App das erste Mal starten wird sie darum bitten, den folgenden "
|
||||
"Code einzuscannen. Der Code enthält alle nötigen Informationen über die "
|
||||
"Veranstaltung."
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:33
|
||||
msgid "3. Start scanning tickets"
|
||||
msgstr "3. Los geht's – Tickets scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:37
|
||||
msgctxt "subevent"
|
||||
msgid "Choose date"
|
||||
msgstr "Termin wählen"
|
||||
#: pretix/plugins/pretixdroid/views.py:42
|
||||
#: pretix/plugins/pretixdroid/views.py:102
|
||||
msgid "The selected configuration does not exist."
|
||||
msgstr "Die ausgewählte Konfiguration existiert nicht."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:46
|
||||
msgid "Show configuration"
|
||||
msgstr "Konfiguration anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:52
|
||||
msgid "Reset authentication token"
|
||||
msgstr "Authentifizierungstoken zurücksetzen"
|
||||
#: pretix/plugins/pretixdroid/views.py:100
|
||||
msgid "The selected configuration has been deleted."
|
||||
msgstr "Die ausgewählte Konfiguration wurde gelöscht."
|
||||
|
||||
#: pretix/plugins/reports/__init__.py:10 pretix/plugins/reports/__init__.py:13
|
||||
msgid "Report exporter"
|
||||
@@ -10670,6 +10749,24 @@ msgstr "Deutsch"
|
||||
msgid "German (informal)"
|
||||
msgstr "Deutsch (Du)"
|
||||
|
||||
#~ msgid "App download"
|
||||
#~ msgstr "App-Download"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you start the app for the first time, it will request that you scan "
|
||||
#~ "the following code. The code tells the app all it needs about your event."
|
||||
#~ msgstr ""
|
||||
#~ "Wenn Sie die App das erste Mal starten wird sie darum bitten, den "
|
||||
#~ "folgenden Code einzuscannen. Der Code enthält alle nötigen Informationen "
|
||||
#~ "über die Veranstaltung."
|
||||
|
||||
#~ msgctxt "subevent"
|
||||
#~ msgid "Choose date"
|
||||
#~ msgstr "Termin wählen"
|
||||
|
||||
#~ msgid "Reset authentication token"
|
||||
#~ msgstr "Authentifizierungstoken zurücksetzen"
|
||||
|
||||
#~ msgid "Download calendar as iCal file"
|
||||
#~ msgstr "Kalender als iCal herunterladen"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-27 07:31+0000\n"
|
||||
"POT-Creation-Date: 2017-08-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2017-08-27 09:35+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: \n"
|
||||
|
||||
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-27 07:30+0000\n"
|
||||
"PO-Revision-Date: 2017-08-27 09:35+0200\n"
|
||||
"POT-Creation-Date: 2017-08-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2017-08-29 23:17+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: Raphael Michel <michel@rami.io>\n"
|
||||
"Language: de\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.0.3\n"
|
||||
"X-Generator: Poedit 2.0.2\n"
|
||||
|
||||
#: pretix/base/exporters/answers.py:18
|
||||
msgid "Answers to file upload questions"
|
||||
@@ -1036,6 +1036,8 @@ msgstr "Antwort"
|
||||
#: pretix/control/templates/pretixcontrol/waitinglist/index.html:119
|
||||
#: pretix/plugins/checkinlists/exporters.py:69
|
||||
#: pretix/plugins/checkinlists/exporters.py:109
|
||||
#: pretix/plugins/pretixdroid/models.py:15
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:46
|
||||
#: pretix/plugins/reports/exporters.py:248
|
||||
msgctxt "subevent"
|
||||
msgid "Date"
|
||||
@@ -1229,6 +1231,8 @@ msgstr "Das Produkt \"{item}\" ist nicht mehr verfügbar."
|
||||
#: pretix/base/models/orders.py:549 pretix/control/views/item.py:436
|
||||
#: pretix/control/views/vouchers.py:81 pretix/control/views/vouchers.py:82
|
||||
#: pretix/plugins/checkinlists/exporters.py:124
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:71
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:72
|
||||
#: pretix/presale/checkoutflow.py:477
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@@ -1238,6 +1242,8 @@ msgstr "Ja"
|
||||
#: pretix/control/views/vouchers.py:82
|
||||
#: pretix/plugins/checkinlists/exporters.py:124
|
||||
#: pretix/plugins/paypal/templates/pretixplugins/paypal/action_refund.html:14
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:71
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:72
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/action_refund.html:14
|
||||
#: pretix/presale/checkoutflow.py:479
|
||||
msgid "No"
|
||||
@@ -3766,6 +3772,8 @@ msgstr "Alle Veranstalter"
|
||||
|
||||
#: pretix/control/forms/filter.py:195
|
||||
#: pretix/control/templates/pretixcontrol/organizers/teams.html:39
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:59
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:63
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
@@ -6051,6 +6059,7 @@ msgid "The following products might be no longer available for sale:"
|
||||
msgstr "Die folgenden Produkte stehen möglicherweise nicht mehr zum Verkauf:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/items/quota_edit.html:27
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:48
|
||||
msgid "Items"
|
||||
msgstr "Produkte"
|
||||
|
||||
@@ -8765,6 +8774,45 @@ msgid ""
|
||||
"This plugin allows you to use the pretixdroid Android app for your event."
|
||||
msgstr "Dieses Plugin erlaubt, die pretixdroid-Android-App zu verwenden."
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:11
|
||||
msgid "Can scan all products"
|
||||
msgstr "Kann alle Produkte scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:12
|
||||
msgid "Can scan these products"
|
||||
msgstr "Nur diese Produkte"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:13
|
||||
msgid "pretixdroid 1.6 or newer only"
|
||||
msgstr "pretixdroid 1.6 oder neuer"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:16
|
||||
#, fuzzy
|
||||
#| msgid "Show configuration"
|
||||
msgid "Show information"
|
||||
msgstr "Informationen anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:17
|
||||
msgid ""
|
||||
"If disabled, the device can not see how many tickets exist and how many are "
|
||||
"already scanned. pretixdroid 1.6 or newer only."
|
||||
msgstr ""
|
||||
"Wenn diese Option deaktiviert ist, kann das Gerät nicht sehen wie viele "
|
||||
"Tickets existieren und wie viele bereits gescannt wurden (ab pretixdroid "
|
||||
"1.6)."
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:19
|
||||
msgid "Search allowed"
|
||||
msgstr "Sucher erlaubt"
|
||||
|
||||
#: pretix/plugins/pretixdroid/models.py:20
|
||||
msgid ""
|
||||
"If disabled, the device can not search for attendees by name. pretixdroid "
|
||||
"1.6 or newer only."
|
||||
msgstr ""
|
||||
"Wenn diese Option deaktiviert ist, kann mit dem Gerät nicht nach Namen "
|
||||
"gesucht werden (ab pretixdroid 1.6)."
|
||||
|
||||
#: pretix/plugins/pretixdroid/signals.py:21
|
||||
msgid "pretixdroid"
|
||||
msgstr "pretixdroid"
|
||||
@@ -8799,6 +8847,8 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:5
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:7
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:5
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:8
|
||||
msgid "pretixdroid configuration"
|
||||
msgstr "pretixdroid-Konfiguration"
|
||||
|
||||
@@ -8811,45 +8861,76 @@ msgstr ""
|
||||
"die Tickets scannen und überprüfen kannst."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:11
|
||||
msgid "App download"
|
||||
msgstr "App-Download"
|
||||
msgid "Create app configuration"
|
||||
msgstr "App-Konfiguration erstellen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:15
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:13
|
||||
msgid ""
|
||||
"To start scanning tickets with our Android app, first create a configuration "
|
||||
"code here:"
|
||||
msgstr ""
|
||||
"Um mit unserer Android-App Tickets zu scannen, erstelle hier erst einen "
|
||||
"Konfigurations-Code:"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:30
|
||||
msgid "Create"
|
||||
msgstr "Erstellen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:38
|
||||
msgid "Existing app configurations"
|
||||
msgstr "Bestehende App-Konfigurationen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:44
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:49
|
||||
msgid "Show info"
|
||||
msgstr "Infos anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:50
|
||||
msgid "Allow search"
|
||||
msgstr "Suche erlauben"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:75
|
||||
msgid "Show QR code"
|
||||
msgstr "QR-Code anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:10
|
||||
msgid "Back to overview"
|
||||
msgstr "Zurück zur Übersicht"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:13
|
||||
msgid "1. Download app"
|
||||
msgstr "1. App herunterladen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:17
|
||||
msgid "Download the app from the Google Play Store"
|
||||
msgstr "Lade die App aus dem App Store herunter"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:20
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:22
|
||||
msgid ""
|
||||
"Android, Google Play and the Google Play logo are trademarks of Google Inc."
|
||||
msgstr ""
|
||||
"Android, Google Play und das Google Play-Logo sind eingetragene Marken von "
|
||||
"Google Inc."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:25
|
||||
msgid "App configuration"
|
||||
msgstr "App-Konfiguration"
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:27
|
||||
msgid "2. Scan code"
|
||||
msgstr "2. Code scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:27
|
||||
msgid ""
|
||||
"If you start the app for the first time, it will request that you scan the "
|
||||
"following code. The code tells the app all it needs about your event."
|
||||
msgstr ""
|
||||
"Wenn du die App das erste Mal startest wird sie dich bitten, den folgenden "
|
||||
"Code einzuscannen. Der Code enthält alle nötigen Informationen über die "
|
||||
"Veranstaltung."
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration_code.html:33
|
||||
msgid "3. Start scanning tickets"
|
||||
msgstr "3. Los geht's – Tickets scannen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:37
|
||||
msgctxt "subevent"
|
||||
msgid "Choose date"
|
||||
msgstr "Termin wählen"
|
||||
#: pretix/plugins/pretixdroid/views.py:42
|
||||
#: pretix/plugins/pretixdroid/views.py:102
|
||||
msgid "The selected configuration does not exist."
|
||||
msgstr "Die ausgewählte Konfiguration existiert nicht."
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:46
|
||||
msgid "Show configuration"
|
||||
msgstr "Konfiguration anzeigen"
|
||||
|
||||
#: pretix/plugins/pretixdroid/templates/pretixplugins/pretixdroid/configuration.html:52
|
||||
msgid "Reset authentication token"
|
||||
msgstr "Authentifizierungstoken zurücksetzen"
|
||||
#: pretix/plugins/pretixdroid/views.py:100
|
||||
msgid "The selected configuration has been deleted."
|
||||
msgstr "Die ausgewählte Konfiguration wurde gelöscht."
|
||||
|
||||
#: pretix/plugins/reports/__init__.py:10 pretix/plugins/reports/__init__.py:13
|
||||
msgid "Report exporter"
|
||||
@@ -10641,6 +10722,24 @@ msgstr "Deutsch"
|
||||
msgid "German (informal)"
|
||||
msgstr "Deutsch (Du)"
|
||||
|
||||
#~ msgid "App download"
|
||||
#~ msgstr "App-Download"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you start the app for the first time, it will request that you scan "
|
||||
#~ "the following code. The code tells the app all it needs about your event."
|
||||
#~ msgstr ""
|
||||
#~ "Wenn du die App das erste Mal startest wird sie dich bitten, den "
|
||||
#~ "folgenden Code einzuscannen. Der Code enthält alle nötigen Informationen "
|
||||
#~ "über die Veranstaltung."
|
||||
|
||||
#~ msgctxt "subevent"
|
||||
#~ msgid "Choose date"
|
||||
#~ msgstr "Termin wählen"
|
||||
|
||||
#~ msgid "Reset authentication token"
|
||||
#~ msgstr "Authentifizierungstoken zurücksetzen"
|
||||
|
||||
#~ msgid "Download calendar as iCal file"
|
||||
#~ msgstr "Kalender als iCal herunterladen"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-27 07:31+0000\n"
|
||||
"POT-Creation-Date: 2017-08-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2017-08-27 09:35+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: \n"
|
||||
|
||||
23
src/pretix/plugins/pretixdroid/forms.py
Normal file
23
src/pretix/plugins/pretixdroid/forms.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django import forms
|
||||
|
||||
from pretix.plugins.pretixdroid.models import AppConfiguration
|
||||
|
||||
|
||||
class AppConfigurationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AppConfiguration
|
||||
fields = ('all_items', 'items', 'subevent', 'show_info', 'allow_search')
|
||||
widgets = {
|
||||
'items': forms.CheckboxSelectMultiple(attrs={
|
||||
'data-inverse-dependency': '#id_all_items'
|
||||
}),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
super().__init__(**kwargs)
|
||||
self.fields['items'].queryset = self.event.items.all()
|
||||
if self.event.has_subevents:
|
||||
self.fields['subevent'].queryset = self.event.subevents.all()
|
||||
else:
|
||||
del self.fields['subevent']
|
||||
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.4 on 2017-08-29 13:08
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def runfwd(app, schema_editor):
|
||||
EventSettingsStore = app.get_model('pretixbase', 'Event_SettingsStore')
|
||||
AppConfiguration = app.get_model('pretixdroid', 'AppConfiguration')
|
||||
|
||||
for setting in EventSettingsStore.objects.filter(key='pretixdroid_key'):
|
||||
AppConfiguration.objects.create(
|
||||
event=setting.object,
|
||||
key=setting.value,
|
||||
all_items=True
|
||||
)
|
||||
setting.delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0074_auto_20170825_1258'),
|
||||
('pretixdroid', '0002_auto_20161208_1644'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AppConfiguration',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.CharField(db_index=True, max_length=190, unique=True)),
|
||||
('all_items', models.BooleanField(default=True)),
|
||||
('allow_search', models.BooleanField(default=True)),
|
||||
('show_info', models.BooleanField(default=True)),
|
||||
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Event')),
|
||||
('items', models.ManyToManyField(blank=True, to='pretixbase.Item')),
|
||||
('subevent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pretixbase.SubEvent')),
|
||||
],
|
||||
),
|
||||
migrations.RunPython(
|
||||
runfwd, migrations.RunPython.noop
|
||||
)
|
||||
]
|
||||
27
src/pretix/plugins/pretixdroid/models.py
Normal file
27
src/pretix/plugins/pretixdroid/models.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import string
|
||||
|
||||
from django.db import models
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
|
||||
|
||||
class AppConfiguration(models.Model):
|
||||
event = models.ForeignKey('pretixbase.Event')
|
||||
key = models.CharField(max_length=190, unique=True, db_index=True)
|
||||
all_items = models.BooleanField(default=True, verbose_name=_('Can scan all products'))
|
||||
items = models.ManyToManyField('pretixbase.Item', blank=True, verbose_name=_('Can scan these products'))
|
||||
subevent = models.ForeignKey('pretixbase.SubEvent', null=True, blank=True,
|
||||
verbose_name=pgettext_lazy('subevent', 'Date'))
|
||||
show_info = models.BooleanField(default=True, verbose_name=_('Show information'),
|
||||
help_text=_('If disabled, the device can not see how many tickets exist and how '
|
||||
'many are already scanned. pretixdroid 1.6 or newer only.'))
|
||||
allow_search = models.BooleanField(default=True, verbose_name=_('Search allowed'),
|
||||
help_text=_('If disabled, the device can not search for attendees by name. '
|
||||
'pretixdroid 1.6 or newer only.'))
|
||||
|
||||
def save(self, **kwargs):
|
||||
if not self.key:
|
||||
self.key = get_random_string(
|
||||
length=32, allowed_chars=string.ascii_uppercase + string.ascii_lowercase + string.digits
|
||||
)
|
||||
return super().save(**kwargs)
|
||||
@@ -8,53 +8,81 @@
|
||||
<p>{% blocktrans trimmed %}
|
||||
pretixdroid is an Android app that you can use to control tickets at the entrance of your event.
|
||||
{% endblocktrans %}</p>
|
||||
<h2>{% trans "App download" %}</h2>
|
||||
<p>
|
||||
<a href="http://play.google.com/store/apps/details?id=eu.pretix.pretixdroid">
|
||||
<img src="{% static "pretixplugins/pretixdroid/play_store_en.png" %}" alt="
|
||||
{% trans "Download the app from the Google Play Store" %}" height="70">
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Android, Google Play and the Google Play logo are trademarks of Google Inc.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
<h2>{% trans "App configuration" %}</h2>
|
||||
<h2>{% trans "Create app configuration" %}</h2>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
If you start the app for the first time, it will request that you scan the following code.
|
||||
The code tells the app all it needs about your event.
|
||||
To start scanning tickets with our Android app, first create a configuration code here:
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
<p>
|
||||
{% if request.event.has_subevents %}
|
||||
<select name="subevent" class="form-control">
|
||||
<option value="">{% trans "Choose date" context "subevent" %}</option>
|
||||
{% for se in request.event.subevents.all %}
|
||||
<option value="{{ se.id }}"
|
||||
{% if request.GET.subevent|add:0 == se.id %}selected="selected"{% endif %}>
|
||||
{{ se.name }} – {{ se.get_date_range_display }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
<button class="btn btn-primary" type="submit">{% trans "Show configuration" %}</button>
|
||||
</p>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors add_form %}
|
||||
{% bootstrap_field add_form.all_items layout="horizontal" %}
|
||||
{% bootstrap_field add_form.items layout="horizontal" %}
|
||||
{% bootstrap_field add_form.show_info layout="horizontal" %}
|
||||
{% bootstrap_field add_form.allow_search layout="horizontal" %}
|
||||
{% if add_form.subevent %}
|
||||
{% bootstrap_field add_form.subevent layout="horizontal" %}
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-3 col-md-9">
|
||||
<button type="submit" class="btn btn-primary btn-save" name="add" value="1">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
{% if configs %}
|
||||
<h2>{% trans "Existing app configurations" %}</h2>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "ID" %}</th>
|
||||
{% if request.event.has_subevents %}
|
||||
<th>{% trans "Date" context "subevent" %}</th>
|
||||
{% endif %}
|
||||
<th>{% trans "Items" %}</th>
|
||||
<th>{% trans "Show info" %}</th>
|
||||
<th>{% trans "Allow search" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ac in configs %}
|
||||
<tr>
|
||||
<td>{{ ac.key|slice:"0:8" }}…</td>
|
||||
{% if request.event.has_subevents %}
|
||||
<td>{% if ac.subevent %}{{ ac.subevent }}{% else %}{% trans "All" %}{% endif %}</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{% if ac.all_items %}
|
||||
{% trans "All" %}
|
||||
{% else %}
|
||||
{% for item in ac.items.all %}
|
||||
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item.name }}</a>
|
||||
{% if loop.revindex0 > 0 %}<br>{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if ac.show_info %}{% trans "Yes" %}{% else %}{% trans "No" %}{% endif %}</td>
|
||||
<td>{% if ac.allow_search %}{% trans "Yes" %}{% else %}{% trans "No" %}{% endif %}</td>
|
||||
<td class="text-right">
|
||||
<a href="{% url "plugins:pretixdroid:config.code" organizer=request.event.organizer.slug event=request.event.slug config=ac.pk %}" class="btn btn-default">
|
||||
<span class="fa fa-qrcode"></span> {% trans "Show QR code" %}
|
||||
</a>
|
||||
<button class="btn btn-danger" name="delete" value="{{ ac.pk }}">
|
||||
<span class="fa fa-trash"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if not request.event.has_subevents or subevent %}
|
||||
<div id="qrcodeCanvas"></div>
|
||||
<a href="?flush_key=1" class="btn btn-default">{% trans "Reset authentication token" %}</a>
|
||||
<script type="text/json" id="qrdata">
|
||||
{{ qrdata|safe }}
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
<script type="text/javascript" src="{% static "pretixplugins/pretixdroid/pretixdroid.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load staticfiles %}
|
||||
{% block title %}{% trans "pretixdroid configuration" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>
|
||||
{% trans "pretixdroid configuration" %}
|
||||
<a href="{% url "plugins:pretixdroid:config" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default">
|
||||
{% trans "Back to overview" %}
|
||||
</a>
|
||||
</h1>
|
||||
<h2>{% trans "1. Download app" %}</h2>
|
||||
<p>
|
||||
<a href="http://play.google.com/store/apps/details?id=eu.pretix.pretixdroid">
|
||||
<img src="{% static "pretixplugins/pretixdroid/play_store_en.png" %}" alt="
|
||||
{% trans "Download the app from the Google Play Store" %}" height="70">
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Android, Google Play and the Google Play logo are trademarks of Google Inc.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
<h2>{% trans "2. Scan code" %}</h2>
|
||||
<div id="qrcodeCanvas"></div>
|
||||
<script type="text/json" id="qrdata">
|
||||
{{ qrdata|safe }}
|
||||
|
||||
</script>
|
||||
<h2>{% trans "3. Start scanning tickets" %}</h2>
|
||||
<script type="text/javascript" src="{% static "pretixplugins/pretixdroid/pretixdroid.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -14,8 +14,10 @@ pretixdroid_api_patterns = [
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pretixdroid/', views.ConfigView.as_view(),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pretixdroid/$', views.ConfigView.as_view(),
|
||||
name='config'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pretixdroid/(?P<config>\d+)/$',
|
||||
views.ConfigCodeView.as_view(), name='config.code'),
|
||||
url(r'^pretixdroid/api/(?P<organizer>[^/]+)/(?P<event>[^/]+)/(?P<subevent>\d+)/',
|
||||
include(pretixdroid_api_patterns)),
|
||||
url(r'^pretixdroid/api/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include(pretixdroid_api_patterns)),
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import json
|
||||
import logging
|
||||
import string
|
||||
|
||||
import dateutil.parser
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
from django.db.models import Count, Q
|
||||
from django.http import (
|
||||
HttpResponseForbidden, HttpResponseNotFound, JsonResponse,
|
||||
)
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.generic import TemplateView, View
|
||||
|
||||
@@ -22,44 +24,93 @@ from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import (
|
||||
build_absolute_uri as event_absolute_uri,
|
||||
)
|
||||
from pretix.plugins.pretixdroid.forms import AppConfigurationForm
|
||||
from pretix.plugins.pretixdroid.models import AppConfiguration
|
||||
|
||||
logger = logging.getLogger('pretix.plugins.pretixdroid')
|
||||
API_VERSION = 3
|
||||
|
||||
|
||||
class ConfigCodeView(EventPermissionRequiredMixin, TemplateView):
|
||||
template_name = 'pretixplugins/pretixdroid/configuration_code.html'
|
||||
permission = 'can_change_orders'
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
try:
|
||||
self.object = self.request.event.appconfiguration_set.get(pk=kwargs.get("config"))
|
||||
except AppConfiguration.DoesNotExist:
|
||||
messages.error(request, _('The selected configuration does not exist.'))
|
||||
return redirect(reverse('plugins:pretixdroid:config', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
}))
|
||||
return super().get(request, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug
|
||||
})
|
||||
if self.object.subevent:
|
||||
url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'subevent': self.object.subevent.pk
|
||||
})
|
||||
|
||||
ctx['qrdata'] = json.dumps({
|
||||
'version': API_VERSION,
|
||||
'url': url[:-7], # the slice removes the redeem/ part at the end
|
||||
'key': self.object.key,
|
||||
'allow_search': self.object.allow_search,
|
||||
'show_info': self.object.show_info
|
||||
})
|
||||
return ctx
|
||||
|
||||
|
||||
class ConfigView(EventPermissionRequiredMixin, TemplateView):
|
||||
template_name = 'pretixplugins/pretixdroid/configuration.html'
|
||||
permission = 'can_change_orders'
|
||||
|
||||
@cached_property
|
||||
def add_form(self):
|
||||
return AppConfigurationForm(
|
||||
event=self.request.event,
|
||||
instance=AppConfiguration(event=self.request.event),
|
||||
data=self.request.POST if self.request.method == "POST" and "add" in self.request.POST else None
|
||||
)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if "add" in self.request.POST and self.add_form.is_valid():
|
||||
self.add_form.save()
|
||||
self.request.event.log_action('pretix.plugins.pretixdroid.config.added', user=self.request.user,
|
||||
data=dict(self.add_form.cleaned_data))
|
||||
return redirect(reverse('plugins:pretixdroid:config.code', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'config': self.add_form.instance.pk
|
||||
}))
|
||||
elif "delete" in self.request.POST:
|
||||
try:
|
||||
ac = self.request.event.appconfiguration_set.get(pk=request.POST.get("delete"))
|
||||
self.request.event.log_action('pretix.plugins.pretixdroid.config.deleted', user=self.request.user,
|
||||
data={'id': ac.pk})
|
||||
ac.delete()
|
||||
messages.success(request, _('The selected configuration has been deleted.'))
|
||||
except AppConfiguration.DoesNotExist:
|
||||
messages.error(request, _('The selected configuration does not exist.'))
|
||||
return redirect(reverse('plugins:pretixdroid:config', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
}))
|
||||
else:
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
key = self.request.event.settings.get('pretixdroid_key')
|
||||
if not key or 'flush_key' in self.request.GET:
|
||||
key = get_random_string(length=32,
|
||||
allowed_chars=string.ascii_uppercase + string.ascii_lowercase + string.digits)
|
||||
self.request.event.settings.set('pretixdroid_key', key)
|
||||
|
||||
subevent = None
|
||||
url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug
|
||||
})
|
||||
if self.request.event.has_subevents:
|
||||
if self.request.GET.get('subevent'):
|
||||
subevent = get_object_or_404(SubEvent, event=self.request.event, pk=self.request.GET['subevent'])
|
||||
url = build_absolute_uri('plugins:pretixdroid:api.redeem', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'subevent': subevent.pk
|
||||
})
|
||||
|
||||
ctx['subevent'] = subevent
|
||||
|
||||
ctx['qrdata'] = json.dumps({
|
||||
'version': API_VERSION,
|
||||
'url': url[:-7], # the slice removes the redeem/ part at the end
|
||||
'key': key,
|
||||
})
|
||||
ctx['add_form'] = self.add_form
|
||||
ctx['configs'] = self.request.event.appconfiguration_set.prefetch_related('items')
|
||||
return ctx
|
||||
|
||||
|
||||
@@ -75,13 +126,16 @@ class ApiView(View):
|
||||
except Event.DoesNotExist:
|
||||
return HttpResponseNotFound('Unknown event')
|
||||
|
||||
if (not self.event.settings.get('pretixdroid_key')
|
||||
or self.event.settings.get('pretixdroid_key') != request.GET.get('key', '-unset-')):
|
||||
try:
|
||||
self.config = self.event.appconfiguration_set.get(key=request.GET.get("key", "-unset-"))
|
||||
except AppConfiguration.DoesNotExist:
|
||||
return HttpResponseForbidden('Invalid key')
|
||||
|
||||
self.subevent = None
|
||||
if self.event.has_subevents:
|
||||
if 'subevent' in kwargs:
|
||||
if self.config.subevent:
|
||||
self.subevent = self.config.subevent
|
||||
elif 'subevent' in kwargs:
|
||||
self.subevent = get_object_or_404(SubEvent, event=self.event, pk=kwargs['subevent'])
|
||||
else:
|
||||
return HttpResponseForbidden('No subevent selected.')
|
||||
@@ -112,7 +166,10 @@ class ApiRedeemView(ApiView):
|
||||
op = OrderPosition.objects.select_related('item', 'variation', 'order', 'addon_to').get(
|
||||
order__event=self.event, secret=secret, subevent=self.subevent
|
||||
)
|
||||
if op.order.status == Order.STATUS_PAID or force:
|
||||
if not self.config.all_items and op.item_id not in [i.pk for i in self.config.items.all()]:
|
||||
response['status'] = 'error'
|
||||
response['reason'] = 'product'
|
||||
elif op.order.status == Order.STATUS_PAID or force:
|
||||
ci, created = Checkin.objects.get_or_create(position=op, defaults={
|
||||
'datetime': dt,
|
||||
'nonce': nonce,
|
||||
@@ -186,14 +243,20 @@ class ApiSearchView(ApiView):
|
||||
}
|
||||
|
||||
if len(query) >= 4:
|
||||
ops = OrderPosition.objects.select_related('item', 'variation', 'order', 'addon_to', 'order__invoice_address').filter(
|
||||
Q(order__event=self.event)
|
||||
& Q(
|
||||
Q(secret__istartswith=query) | Q(attendee_name__icontains=query) | Q(order__code__istartswith=query)
|
||||
| Q(order__invoice_address__name__icontains=query)
|
||||
)
|
||||
& Q(subevent=self.subevent)
|
||||
).annotate(checkin_cnt=Count('checkins'))[:25]
|
||||
qs = OrderPosition.objects.select_related('item', 'variation', 'order', 'addon_to', 'order__invoice_address')
|
||||
if not self.config.allow_search:
|
||||
ops = qs.filter(
|
||||
Q(order__event=self.event) & Q(secret__istartswith=query) & Q(subevent=self.subevent)
|
||||
).annotate(checkin_cnt=Count('checkins'))[:25]
|
||||
else:
|
||||
ops = qs.filter(
|
||||
Q(order__event=self.event)
|
||||
& Q(
|
||||
Q(secret__istartswith=query) | Q(attendee_name__icontains=query) | Q(order__code__istartswith=query)
|
||||
| Q(order__invoice_address__name__icontains=query)
|
||||
)
|
||||
& Q(subevent=self.subevent)
|
||||
).annotate(checkin_cnt=Count('checkins'))[:25]
|
||||
|
||||
response['results'] = [serialize_op(op, bool(op.checkin_cnt)) for op in ops]
|
||||
else:
|
||||
@@ -210,7 +273,11 @@ class ApiDownloadView(ApiView):
|
||||
|
||||
ops = OrderPosition.objects.select_related('item', 'variation', 'order', 'addon_to').filter(
|
||||
Q(order__event=self.event) & Q(subevent=self.subevent)
|
||||
).annotate(checkin_cnt=Count('checkins'))
|
||||
)
|
||||
if not self.config.all_items:
|
||||
ops = ops.filter(item__in=self.config.items.all())
|
||||
|
||||
ops = ops.annotate(checkin_cnt=Count('checkins'))
|
||||
response['results'] = [serialize_op(op, bool(op.checkin_cnt)) for op in ops]
|
||||
|
||||
return JsonResponse(response)
|
||||
|
||||
@@ -8,6 +8,7 @@ from pretix.base.models import (
|
||||
Checkin, Event, InvoiceAddress, Item, ItemVariation, Order, OrderPosition,
|
||||
Organizer, Team, User,
|
||||
)
|
||||
from pretix.plugins.pretixdroid.models import AppConfiguration
|
||||
from pretix.plugins.pretixdroid.views import API_VERSION
|
||||
|
||||
|
||||
@@ -44,23 +45,9 @@ def env():
|
||||
return event, user, o1, op1, op2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_flush_key(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
|
||||
client.get('/control/event/%s/%s/pretixdroid/' % (env[0].organizer.slug, env[0].slug))
|
||||
env[0].settings.flush()
|
||||
assert env[0].settings.get('pretixdroid_key') == 'abcdefg'
|
||||
|
||||
client.get('/control/event/%s/%s/pretixdroid/?flush_key=1' % (env[0].organizer.slug, env[0].slug))
|
||||
env[0].settings.flush()
|
||||
assert env[0].settings.get('pretixdroid_key') != 'abcdefg'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_datetime(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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'),
|
||||
@@ -73,7 +60,7 @@ def test_custom_datetime(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_only_once(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
|
||||
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
|
||||
data={'secret': '1234'})
|
||||
@@ -87,9 +74,26 @@ def test_only_once(client, env):
|
||||
assert jdata['reason'] == 'already_redeemed'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_item_scope(client, env):
|
||||
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', all_items=False)
|
||||
ac.items.add(env[4].item)
|
||||
|
||||
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):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
|
||||
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
|
||||
data={'secret': '1234', 'nonce': 'fooobar'})
|
||||
@@ -105,7 +109,7 @@ def test_reupload_same_nonce(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_forced_multiple(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
|
||||
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
|
||||
data={'secret': '1234'})
|
||||
@@ -120,7 +124,7 @@ def test_forced_multiple(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_require_paid(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
env[2].status = Order.STATUS_PENDING
|
||||
env[2].save()
|
||||
|
||||
@@ -133,7 +137,7 @@ def test_require_paid(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unknown(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
|
||||
resp = client.post('/pretixdroid/api/%s/%s/redeem/?key=%s' % (env[0].organizer.slug, env[0].slug, 'abcdefg'),
|
||||
data={'secret': '4321'})
|
||||
@@ -158,17 +162,36 @@ def test_unknown_event(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_search(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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'] == '5678910'
|
||||
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
|
||||
env[0].organizer.slug, env[0].slug, 'abcdefg', 'Peter'))
|
||||
jdata = json.loads(resp.content.decode("utf-8"))
|
||||
assert len(jdata['results']) == 1
|
||||
assert jdata['results'][0]['secret'] == '5678910'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_search_restricted(client, env):
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg', 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"))
|
||||
assert len(jdata['results']) == 1
|
||||
assert jdata['results'][0]['secret'] == '5678910'
|
||||
resp = client.get('/pretixdroid/api/%s/%s/search/?key=%s&query=%s' % (
|
||||
env[0].organizer.slug, env[0].slug, 'abcdefg', 'Peter'))
|
||||
jdata = json.loads(resp.content.decode("utf-8"))
|
||||
assert len(jdata['results']) == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_search_invoice_name(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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'))
|
||||
@@ -179,7 +202,7 @@ def test_search_invoice_name(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_download_all_data(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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
|
||||
@@ -187,9 +210,19 @@ def test_download_all_data(client, env):
|
||||
assert jdata['results'][1]['secret'] == '5678910'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_download_item_restriction(client, env):
|
||||
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', 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"))
|
||||
assert len(jdata['results']) == 1
|
||||
assert jdata['results'][0]['secret'] == env[4].secret
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_status(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
Checkin.objects.create(position=env[3])
|
||||
resp = client.get('/pretixdroid/api/%s/%s/status/?key=%s' % (
|
||||
env[0].organizer.slug, env[0].slug, 'abcdefg'))
|
||||
|
||||
@@ -8,6 +8,7 @@ from pretix.base.models import (
|
||||
Checkin, Event, Item, ItemVariation, Order, OrderPosition, Organizer, Team,
|
||||
User,
|
||||
)
|
||||
from pretix.plugins.pretixdroid.models import AppConfiguration
|
||||
from pretix.plugins.pretixdroid.views import API_VERSION
|
||||
|
||||
|
||||
@@ -47,23 +48,9 @@ def env():
|
||||
return event, user, o1, op1, op2, se1, se2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_config(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
|
||||
r = client.get('/control/event/%s/%s/pretixdroid/' % (env[0].organizer.slug, env[0].slug))
|
||||
print(r.content)
|
||||
assert 'qrcodeCanvas' not in r.rendered_content
|
||||
|
||||
r = client.get('/control/event/%s/%s/pretixdroid/?subevent=%d' % (env[0].organizer.slug, env[0].slug, env[5].pk))
|
||||
assert 'qrcodeCanvas' in r.rendered_content
|
||||
assert '/%d/' % env[5].pk in r.rendered_content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_datetime(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
|
||||
dt = now() - timedelta(days=1)
|
||||
dt = dt.replace(microsecond=0)
|
||||
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
|
||||
@@ -77,7 +64,7 @@ def test_custom_datetime(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_wrong_subevent(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
|
||||
resp = client.post('/pretixdroid/api/%s/%s/%d/redeem/?key=%s' % (
|
||||
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg'
|
||||
@@ -93,9 +80,30 @@ def test_wrong_subevent(client, env):
|
||||
assert jdata['status'] == 'ok'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_other_subevent_not_allowed(client, env):
|
||||
ac = AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
|
||||
|
||||
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'
|
||||
|
||||
ac.subevent = env[6]
|
||||
ac.save()
|
||||
|
||||
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'] == 'ok'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unknown_subevent(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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'})
|
||||
@@ -112,7 +120,7 @@ def test_no_subevent(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_search(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg')
|
||||
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'))
|
||||
jdata = json.loads(resp.content.decode("utf-8"))
|
||||
@@ -126,7 +134,7 @@ def test_search(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_download_all_data(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
|
||||
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"))
|
||||
@@ -136,7 +144,7 @@ def test_download_all_data(client, env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_status(client, env):
|
||||
env[0].settings.set('pretixdroid_key', 'abcdefg')
|
||||
AppConfiguration.objects.create(event=env[0], key='abcdefg', subevent=env[5])
|
||||
Checkin.objects.create(position=env[3])
|
||||
resp = client.get('/pretixdroid/api/%s/%s/%d/status/?key=%s' % (
|
||||
env[0].organizer.slug, env[0].slug, env[5].pk, 'abcdefg'))
|
||||
|
||||
Reference in New Issue
Block a user