From f4f090506bd3cc6db07d762ac2960f1c11829dc7 Mon Sep 17 00:00:00 2001 From: UpdateBot Date: Tue, 4 Feb 2025 22:11:52 +0100 Subject: [PATCH 01/10] Update Texts --- .gitea/workflows/cicd.yaml | 18 +++ doc/user/glossary.rst | 4 +- src/pretix/locale/de/LC_MESSAGES/django.po | 124 +++++++-------- .../locale/de_Informal/LC_MESSAGES/django.po | 146 +++++++++--------- 4 files changed, 155 insertions(+), 137 deletions(-) create mode 100644 .gitea/workflows/cicd.yaml diff --git a/.gitea/workflows/cicd.yaml b/.gitea/workflows/cicd.yaml new file mode 100644 index 000000000..3ddc71a06 --- /dev/null +++ b/.gitea/workflows/cicd.yaml @@ -0,0 +1,18 @@ +name: Build Deploy email notification tool +run-name: ${{ gitea.actor }} building new version of the email notification tool +on: + push: + workflow_dispatch: + +jobs: + Apply-Kubernetes-Resources: + runs-on: podman + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Login to Docker Registry + run: podman login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_TOKEN }} cr.ortlerstrasse.de + - name: Build Docker image + run: podman build -t cr.ortlerstrasse.de/cgo/pretix:2025.1.0 . + - name: Push Docker image + run: podman push cr.ortlerstrasse.de/cgo/pretix:2025.1.0 \ No newline at end of file diff --git a/doc/user/glossary.rst b/doc/user/glossary.rst index 678de28dd..8c66ec536 100644 --- a/doc/user/glossary.rst +++ b/doc/user/glossary.rst @@ -107,7 +107,7 @@ going to develop around pretix, for example connect to pretix through our API, y | |:de:| Bestellnummer - An order code is the unique identifier of an order, usually consisting of 5 numbers and letters. * - | |:gb:| **Customer** - | |:de:| Kund\*in + | |:de:| Kunde - A customer is the person who buys a ticket, regardless of who will be using it later. A customer can be defined just by an email address or a name, or can have a persistent **customer account** they can log in to. * - | |:gb:| **Order position** @@ -115,7 +115,7 @@ going to develop around pretix, for example connect to pretix through our API, y - An order position is a single line inside an order, representing the purchase of one specific product. If the product is an admission product, this represents an attendee. * - | |:gb:| **Attendee** - | |:de:| Teilnehmer\*in + | |:de:| Teilnehmer - An attendee is the person designated to use a specific order position to access the event. It may be the same or a different person as the customer. * - | |:gb:| **Fee** diff --git a/src/pretix/locale/de/LC_MESSAGES/django.po b/src/pretix/locale/de/LC_MESSAGES/django.po index 15e9cb6a6..cec389753 100644 --- a/src/pretix/locale/de/LC_MESSAGES/django.po +++ b/src/pretix/locale/de/LC_MESSAGES/django.po @@ -822,7 +822,7 @@ msgid "" "Download a ZIP file including all files that have been uploaded by your " "customers while creating an order." msgstr "" -"ZIP-Datei mit allen Dateien, die von Kund*innen im Bestellprozess als " +"ZIP-Datei mit allen Dateien, die von Kunden im Bestellprozess als " "Antwort auf eine Frage hochgeladen wurden." #: pretix/base/exporters/answers.py:66 pretix/base/models/items.py:1766 @@ -1838,8 +1838,8 @@ msgid "" "Download a text file with all email addresses collected either from buyers " "or from ticket holders." msgstr "" -"Textdatei mit allen E-Mail-Adressen, die von Käufer*innen und " -"Ticketinhaber*innen eingesammelt wurden." +"Textdatei mit allen E-Mail-Adressen, die von Käufern und " +"Ticketinhaber eingesammelt wurden." #: pretix/base/exporters/mail.py:76 pretix/plugins/reports/exporters.py:487 #: pretix/plugins/reports/exporters.py:669 @@ -2203,7 +2203,7 @@ msgstr "Produkt" #: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 #: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:37 msgid "Attendee name" -msgstr "Name Teilnehmer*in" +msgstr "Name Teilnehmer" #: pretix/base/exporters/orderlist.py:602 pretix/base/forms/questions.py:667 #: pretix/base/models/customers.py:307 pretix/base/models/orders.py:1510 @@ -2213,7 +2213,7 @@ msgstr "Name Teilnehmer*in" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:176 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:179 msgid "Attendee email" -msgstr "E-Mail Teilnehmer*in" +msgstr "E-Mail Teilnehmer" #: pretix/base/exporters/orderlist.py:609 pretix/base/models/vouchers.py:312 #: pretix/control/templates/pretixcontrol/vouchers/bulk.html:5 @@ -3593,7 +3593,7 @@ msgstr "Bitte wählen Sie einen gültigen Staat aus." #: pretix/base/modelimport_orders.py:325 pretix/control/forms/filter.py:651 msgid "Attendee email address" -msgstr "Teilnehmer*innen-E-Mail-Adresse" +msgstr "Teilnehmer-E-Mail-Adresse" #: pretix/base/modelimport_orders.py:341 pretix/base/modelimport_orders.py:352 #: pretix/base/modelimport_orders.py:363 pretix/base/modelimport_orders.py:374 @@ -3605,7 +3605,7 @@ msgstr "Teilnehmer*innen-E-Mail-Adresse" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:197 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:200 msgid "Attendee address" -msgstr "Teilnehmer*innen-Adresse" +msgstr "Teilnehmer-Adresse" #: pretix/base/modelimport_orders.py:409 msgid "State" @@ -7330,7 +7330,7 @@ msgstr "Max Mustermann" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:186 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:189 msgid "Attendee company" -msgstr "Teilnehmer*innen-Firma" +msgstr "Teilnehmer-Firma" #: pretix/base/pdf.py:178 pretix/base/pdf.py:336 #: pretix/base/services/tickets.py:119 pretix/control/views/pdf.py:111 @@ -7339,7 +7339,7 @@ msgstr "Musterfirma GmbH" #: pretix/base/pdf.py:182 msgid "Full attendee address" -msgstr "Volle Teilnehmer*innen-Adresse" +msgstr "Volle Teilnehmer-Adresse" #: pretix/base/pdf.py:183 msgid "" @@ -7357,23 +7357,23 @@ msgstr "" #: pretix/base/pdf.py:187 msgid "Attendee street" -msgstr "Teilnehmer*innen-Straße" +msgstr "Teilnehmer-Straße" #: pretix/base/pdf.py:192 msgid "Attendee ZIP code" -msgstr "Teilnehmer*innen-PLZ" +msgstr "Teilnehmer-PLZ" #: pretix/base/pdf.py:197 msgid "Attendee city" -msgstr "Teilnehmer*innen-Stadt" +msgstr "Teilnehmer-Stadt" #: pretix/base/pdf.py:202 msgid "Attendee state" -msgstr "Teilnehmer*innen-Bundesstaat" +msgstr "Teilnehmer-Bundesstaat" #: pretix/base/pdf.py:207 msgid "Attendee country" -msgstr "Teilnehmer*innen-Land" +msgstr "Teilnehmer-Land" #: pretix/base/pdf.py:219 msgid "Pseudonymization ID (lead scanning)" @@ -7656,7 +7656,7 @@ msgstr "Herr Mustermann" #: pretix/plugins/ticketoutputpdf/exporters.py:99 #, python-brace-format msgid "Attendee name: {part}" -msgstr "Teilnehmer*innenname: {part}" +msgstr "Teilnehmername: {part}" #: pretix/base/pdf.py:671 msgid "Invoice address name for salutation" @@ -8328,7 +8328,7 @@ msgstr "Veranstaltungsort: {location}" #, python-brace-format msgctxt "invoice" msgid "Attendee: {name}" -msgstr "Teilnehmer*in: {name}" +msgstr "Teilnehmer: {name}" #: pretix/base/services/invoices.py:254 pretix/plugins/reports/exporters.py:298 msgctxt "subevent" @@ -9127,7 +9127,7 @@ msgstr "" #: pretix/base/settings.py:338 msgid "Hide prices on attendee ticket page" -msgstr "Preise auf Teilnehmer*innen-Ticket-Seite verstecken" +msgstr "Preise auf Teilnehmer-Ticket-Seite verstecken" #: pretix/base/settings.py:339 msgid "" @@ -9137,13 +9137,13 @@ msgid "" "price." msgstr "" "Wenn eine Person mehrere Tickets erwirbt und E-Mails an alle " -"Teilnehmer*innen verschickt werden, wird mit dieser Option der Ticketpreis " -"auf der Ticket-Seite der einzelnen Teilnehmer*innen versteckt. Nur die " +"Teilnehmer verschickt werden, wird mit dieser Option der Ticketpreis " +"auf der Ticket-Seite der einzelnen Teilnehmer versteckt. Nur die " "Person, welche die Tickets kauft, sieht den Preis." #: pretix/base/settings.py:357 msgid "Ask for attendee names" -msgstr "Namen der Teilnehmer*innen erfragen" +msgstr "Namen der Teilnehmer erfragen" #: pretix/base/settings.py:358 msgid "Ask for a name for all personalized tickets." @@ -9152,11 +9152,11 @@ msgstr "" #: pretix/base/settings.py:367 msgid "Require attendee names" -msgstr "Namen der Teilnehmer*innen erfordern" +msgstr "Namen der Teilnehmer erfordern" #: pretix/base/settings.py:368 msgid "Require customers to fill in the names of all attendees." -msgstr "Erfordere die Eingabe aller Teilnehmer*innen-Namen." +msgstr "Erfordere die Eingabe aller Teilnehmer-Namen." #: pretix/base/settings.py:378 msgid "Ask for email addresses per ticket" @@ -9652,8 +9652,8 @@ msgid "" "but no indication of missing payment will be visible on the ticket pages of " "attendees who did not buy the ticket themselves." msgstr "" -"Die Box mit Zahlungsinstruktionen wird Ticketkäufer*innen weiter angezeigt, " -"aber Teilnehmer*innen, die ihr Ticket nicht selbst gekauft haben, werden " +"Die Box mit Zahlungsinstruktionen wird Ticketkäufern weiter angezeigt, " +"aber Teilnehmern, die ihr Ticket nicht selbst gekauft haben, werden " "keine Anzeichen des fehlenden Zahlungseingangs sehen." #: pretix/base/settings.py:996 @@ -10091,7 +10091,7 @@ msgstr "" #: pretix/base/settings.py:1509 msgid "Show number of check-ins to customer" -msgstr "Zeige Anzahl der Check-ins für Kund*innen an" +msgstr "Zeige Anzahl der Check-ins für Kunden an" #: pretix/base/settings.py:1510 msgid "" @@ -10102,12 +10102,12 @@ msgid "" "failed scans will not be counted, and the user will not see the different " "check-in lists." msgstr "" -"Wenn diese Option aktiv ist, können Kund*innen selbst sehen, wie oft sie die " +"Wenn diese Option aktiv ist, können Kunden selbst sehen, wie oft sie die " "Veranstaltung betreten haben. Das ist normalerweise nicht nötig, aber kann " "nützlich sein, wenn es Tickets gibt, die eine bestimmte Anzahl an Eintritten " -"erlauben, sodass Kund*innen die bisherige Nutzung des Tickets einsehen " +"erlauben, sodass Kunden die bisherige Nutzung des Tickets einsehen " "können. Ausgänge oder fehlgeschlagene Scans werden nicht angezeigt und die " -"Kund*innen sehen keine Aufschlüsselung verschiedener Check-in-Listen." +"Kunden sehen keine Aufschlüsselung verschiedener Check-in-Listen." #: pretix/base/settings.py:1523 msgid "Allow users to download tickets" @@ -10288,7 +10288,7 @@ msgstr "" #: pretix/base/settings.py:1686 pretix/base/settings.py:1695 msgid "Both the attendee and the person who ordered can make changes" msgstr "" -"Sowohl Besteller*in als auch Teilnehmer*innen können Änderungen vornehmen" +"Sowohl Besteller als auch Teilnehmer können Änderungen vornehmen" #: pretix/base/settings.py:1690 msgid "Allow customers to modify their information" @@ -10396,7 +10396,7 @@ msgstr "" #: pretix/base/settings.py:1796 msgid "Allow individual attendees to change their ticket" -msgstr "Erlaubt einzelnen Teilnehmer*innen ihr Ticket zu ändern" +msgstr "Erlaubt einzelnen Teilnehmern ihr Ticket zu ändern" #: pretix/base/settings.py:1797 msgid "" @@ -10408,7 +10408,7 @@ msgid "" msgstr "" "Standardmäßig kann nur die Person, welche die Tickets gekauft hat, " "Änderungen an der Bestellung vornehmen. Wenn diese Option aktiv ist, können " -"auch einzelne Teilnehmer*innen Änderungen vornehmen. Teilnehmer*innen können " +"auch einzelne Teilnehmer Änderungen vornehmen. Teilnehmer können " "jedoch immer nur Änderungen vornehmen, welche die Gesamtkosten der " "Bestellung nicht verändern. Solche Änderungen können nur vom Ticketkäufer " "vorgenommen werden." @@ -10674,7 +10674,7 @@ msgid "" "people." msgstr "" "Sie können dieses Feld benutzen, um zusätzliche Informationen mit Ihren " -"Teilnehmer*innen zu teilen, wie z.B. Anreise-Informationen oder den Link zu " +"Teilnehmer zu teilen, wie z.B. Anreise-Informationen oder den Link zu " "einer digitalen Veranstaltung. Wenn das Feld leer ist, fügen wir automatisch " "einen Link zum Ticketshop, die Einlass-Uhrzeit und den Veranstalter hier " "ein. Es sind keine Platzhalter mit sensiblen personenbezogenen Daten " @@ -10915,8 +10915,8 @@ msgstr "" "Diese Datei wird an die erste E-Mail angehängt, die wir beim Eingang einer " "neuen Bestellung verschicken. Sie kann daher mit den Textvorlagen " "\"Getätigte Bestellung\", \"Kostenlose Bestellung\" oder \"Erhaltene " -"Bestellung\" von oben auftreten. Sie wird ggf. sowohl an Besteller*innen als " -"auch Teilnehmer*innen verschickt. Nicht geeignet zum Versand nicht-" +"Bestellung\" von oben auftreten. Sie wird ggf. sowohl an Besteller als " +"auch Teilnehmer verschickt. Nicht geeignet zum Versand nicht-" "öffentlicher Informationen, da die Datei unabhängig davon verschickt wird, " "ob die Bestellung bezahlt oder freigegeben ist. Um zu vermeiden, dass diese " "wichtige E-Mail nicht ankommt, können nur PDF-Dateien mit maximal {size} MB " @@ -13986,7 +13986,7 @@ msgstr "Check-in-Status" #: pretix/control/forms/filter.py:1888 #: pretix/plugins/checkinlists/exporters.py:107 msgid "All attendees" -msgstr "Alle Teilnehmer*innen" +msgstr "Alle Teilnehmer" #: pretix/control/forms/filter.py:1889 #: pretix/control/templates/pretixcontrol/checkin/index.html:183 @@ -14556,7 +14556,7 @@ msgid "" "people over 65. This ticket includes access to all parts of the event, " "except the VIP area." msgstr "" -"z.B. Dieses reduzierte Ticket ist erhältlich für Vollzeitstudent*innen, " +"z.B. Dieses reduzierte Ticket ist erhältlich für Vollzeitstudent, " "Arbeitslose und Menschen über 65. Das Ticket enthält Zugang zu allen Teilen " "der Veranstaltung außer des VIP-Bereiches." @@ -14813,7 +14813,7 @@ msgstr "" #: pretix/control/forms/orders.py:165 pretix/control/forms/orders.py:212 #: pretix/control/forms/orders.py:226 msgid "Notify customer by email" -msgstr "Kund*in per E-Mail benachrichtigen" +msgstr "Kunde per E-Mail benachrichtigen" #: pretix/control/forms/orders.py:172 msgid "Keep a cancellation fee of" @@ -16141,7 +16141,7 @@ msgstr "Eine individuelle E-Mail wurde verschickt." #: pretix/control/logdisplay.py:479 msgid "A custom email has been sent to an attendee." -msgstr "Eine individuelle E-Mail wurde an eine Teilnehmer*in verschickt." +msgstr "Eine individuelle E-Mail wurde an einen Teilnehmer verschickt." #: pretix/control/logdisplay.py:480 msgid "" @@ -17793,7 +17793,7 @@ msgstr "Terminal-ID" #: pretix/control/templates/pretixcontrol/boxoffice/payment.html:104 msgid "Card holder" -msgstr "Karteninhaber*in" +msgstr "Karteninhaber" #: pretix/control/templates/pretixcontrol/boxoffice/payment.html:108 msgid "Card expiration" @@ -18088,7 +18088,7 @@ msgstr "CSV" #: pretix/control/templates/pretixcontrol/checkin/index.html:73 msgid "No attendee record was found." -msgstr "Keine passenden Teilnehmer*innen gefunden." +msgstr "Keine passenden Teilnehmer gefunden." #: pretix/control/templates/pretixcontrol/checkin/index.html:91 #: pretix/control/templates/pretixcontrol/orders/index.html:128 @@ -20570,7 +20570,7 @@ msgid "" "Only purchases of such products will be considered \"attendees\" for most " "statistical purposes or within some plugins." msgstr "" -"Nur Käufe eines solchen Produkts werden als \"Teilnehmer*innen\" gewertet, " +"Nur Käufe eines solchen Produkts werden als \"Teilnehmer\" gewertet, " "z.B. in Statistiken oder in Funktionen von Erweiterungen." #: pretix/control/templates/pretixcontrol/item/create.html:39 @@ -20649,7 +20649,7 @@ msgid "" "The system will not ask for a name or other attendee details. This only " "affects system-provided fields, you can still add your own questions." msgstr "" -"Das System wird nicht nach einem Namen oder anderen Teilnehmer*innen-Daten " +"Das System wird nicht nach einem Namen oder anderen Teilnehmer-Daten " "fragen. Dies betrifft nur vom System bereitgestellte Felder, eigene Fragen " "können trotzdem hinzugefügt werden." @@ -22787,7 +22787,7 @@ msgstr "Sonstige Datenexporte" #: pretix/control/templates/pretixcontrol/orders/export.html:104 #: pretix/control/templates/pretixcontrol/organizers/export.html:104 msgid "Recommended for new users" -msgstr "Empfohlen für neue Benutzer*innen" +msgstr "Empfohlen für neue Benutzer" #: pretix/control/templates/pretixcontrol/orders/export_delete.html:4 #: pretix/control/templates/pretixcontrol/orders/export_delete.html:6 @@ -23751,7 +23751,7 @@ msgstr "Domains" #: pretix/control/templates/pretixcontrol/organizers/edit.html:301 msgid "This dialog is intended for advanced users." -msgstr "Dieser Dialog ist für fortgeschrittene Anwender*innen gedacht." +msgstr "Dieser Dialog ist für fortgeschrittene Anwender gedacht." #: pretix/control/templates/pretixcontrol/organizers/edit.html:302 msgid "" @@ -25900,7 +25900,7 @@ msgid "" "customers. This way, customers will not be able to discover the waiting list." msgstr "" "Entsprechend Ihrer Veranstaltungseinstellungen werden ausverkaufte Produkte " -"nicht angezeigt. Dies führt dazu, dass Kund*innen die Warteliste nicht " +"nicht angezeigt. Dies führt dazu, dass Kunden die Warteliste nicht " "finden können." #: pretix/control/templates/pretixcontrol/waitinglist/index.html:36 @@ -28154,7 +28154,7 @@ msgstr "PDF-Sammlungen" #: pretix/plugins/badges/exporters.py:423 msgid "Download all attendee badges as one large PDF for printing." -msgstr "Alle Teilnehmer*innen-Badges in einer großen PDF-Datei für den Druck." +msgstr "Alle Teilnehmer-Badges in einer großen PDF-Datei für den Druck." #: pretix/plugins/badges/exporters.py:444 #: pretix/plugins/ticketoutputpdf/exporters.py:80 @@ -28410,7 +28410,7 @@ msgstr "Anderes Bankkonto" #: pretix/plugins/banktransfer/payment.py:91 msgid "Name of account holder" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/banktransfer/payment.py:93 msgid "" @@ -28603,7 +28603,7 @@ msgstr "Bitte überweisen Sie den vollen Betrag auf das folgende Bankkonto:" #: pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_confirm.html:32 #: pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_confirm.html:35 msgid "Account holder" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/banktransfer/payment.py:468 #: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_confirm.html:17 @@ -29314,7 +29314,7 @@ msgid "" "Download a spreadsheet with all attendees that are included in a check-in " "list." msgstr "" -"Tabelle (Excel oder CSV) mit allen Teilnehmer*innen, die in einer Check-in-" +"Tabelle (Excel oder CSV) mit allen Teilnehmer, die in einer Check-in-" "Liste zutrittsberechtigt sind." #: pretix/plugins/checkinlists/exporters.py:497 @@ -30503,7 +30503,7 @@ msgstr "Geplante E-Mails" #: pretix/plugins/sendmail/signals.py:121 msgid "Mass email was sent to customers or attendees." -msgstr "Rundmail wurde an Kunden oder Teilnehmer*innen verschickt." +msgstr "Rundmail wurde an Kunden oder Teilnehmer verschickt." #: pretix/plugins/sendmail/signals.py:122 msgid "Mass email was sent to waiting list entries." @@ -30531,7 +30531,7 @@ msgstr "Eine automatisierte E-Mail wurde an den Besteller verschickt" #: pretix/plugins/sendmail/signals.py:136 msgid "A scheduled email was sent to a ticket holder" -msgstr "Eine automatisierte E-Mail wurde an eine Teilnehmer*in verschickt." +msgstr "Eine automatisierte E-Mail wurde an eine Teilnehmer verschickt." #: pretix/plugins/sendmail/signals.py:137 msgid "An email rule was deleted" @@ -30564,7 +30564,7 @@ msgstr "Alle nicht eingecheckten Kunden" #: pretix/plugins/sendmail/templates/pretixplugins/sendmail/history_fragment_orders.html:23 msgid "Attendee contact addresses" -msgstr "Teilnehmer*innen-E-Mail-Adressen" +msgstr "Teilnehmer-E-Mail-Adressen" #: pretix/plugins/sendmail/templates/pretixplugins/sendmail/history_fragment_orders.html:25 msgid "All contact addresses" @@ -30727,14 +30727,14 @@ msgstr "" #: pretix/plugins/sendmail/views.py:250 msgid "Orders or attendees" -msgstr "Bestellungen oder Teilnehmer*innen" +msgstr "Bestellungen oder Teilnehmer" #: pretix/plugins/sendmail/views.py:251 msgid "" "Send an email to every customer, or to every person a ticket has been " "purchased for, or a combination of both." msgstr "" -"Senden Sie eine E-Mail an alle Ticketkäufer*innen, alle Ticketinhaber*innen " +"Senden Sie eine E-Mail an alle Ticketkäufer, alle Ticketinhaber " "oder eine Kombination aus beiden Gruppen." #: pretix/plugins/sendmail/views.py:417 @@ -31257,23 +31257,23 @@ msgstr "SEPA-Lastschrift" #: pretix/plugins/stripe/payment.py:1232 msgid "Account Holder Name" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/stripe/payment.py:1237 msgid "Account Holder Street" -msgstr "Straße (Kontoinhaber*in)" +msgstr "Straße (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1249 msgid "Account Holder Postal Code" -msgstr "PLZ (Kontoinhaber*in)" +msgstr "PLZ (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1261 msgid "Account Holder City" -msgstr "Stadt (Kontoinhaber*in)" +msgstr "Stadt (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1273 msgid "Account Holder Country" -msgstr "Land (Kontoinhaber*in)" +msgstr "Land (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1317 msgid "Affirm via Stripe" @@ -34680,12 +34680,12 @@ msgstr "" #: pretix/presale/templates/pretixpresale/organizers/customer_profiles.html:11 #: pretix/presale/views/customer.py:378 msgid "Attendee profiles" -msgstr "Teilnehmer*innen-Profile" +msgstr "Teilnehmer-Profile" #: pretix/presale/templates/pretixpresale/organizers/customer_profiles.html:37 msgid "You don’t have any attendee profiles in your account yet." msgstr "" -"In Ihrem Kundenkonto sind noch keine Teilnehmer*innen-Profile gespeichert." +"In Ihrem Kundenkonto sind noch keine Teilnehmer-Profile gespeichert." #: pretix/presale/templates/pretixpresale/organizers/customer_registration.html:6 msgid "Registration" @@ -35742,7 +35742,7 @@ msgstr "Kosovo" #~ "This plugin allows you to generate badges or name tags for your attendees." #~ msgstr "" #~ "Diese Erweiterung erlaubt, Namensschilder oder Badges für die " -#~ "Teilnehmer*innen zu erstellen." +#~ "Teilnehmer zu erstellen." #~ msgid "This plugin allows you to receive payments via PayPal" #~ msgstr "Dieses Plugin erlaubt, Zahlungen über PayPal anzunehmen" diff --git a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po index 6b5ed842c..0b29b757f 100644 --- a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po +++ b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po @@ -823,7 +823,7 @@ msgid "" "Download a ZIP file including all files that have been uploaded by your " "customers while creating an order." msgstr "" -"ZIP-Datei mit allen Dateien, die von Kund*innen im Bestellprozess als " +"ZIP-Datei mit allen Dateien, die von Kunden im Bestellprozess als " "Antwort auf eine Frage hochgeladen wurden." #: pretix/base/exporters/answers.py:66 pretix/base/models/items.py:1766 @@ -1839,8 +1839,8 @@ msgid "" "Download a text file with all email addresses collected either from buyers " "or from ticket holders." msgstr "" -"Textdatei mit allen E-Mail-Adressen, die von Käufer*innen und " -"Ticketinhaber*innen eingesammelt wurden." +"Textdatei mit allen E-Mail-Adressen, die von Käufer und " +"Ticketinhaber eingesammelt wurden." #: pretix/base/exporters/mail.py:76 pretix/plugins/reports/exporters.py:487 #: pretix/plugins/reports/exporters.py:669 @@ -2204,7 +2204,7 @@ msgstr "Produkt" #: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 #: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:37 msgid "Attendee name" -msgstr "Name Teilnehmer*in" +msgstr "Name Teilnehmer" #: pretix/base/exporters/orderlist.py:602 pretix/base/forms/questions.py:667 #: pretix/base/models/customers.py:307 pretix/base/models/orders.py:1510 @@ -2214,7 +2214,7 @@ msgstr "Name Teilnehmer*in" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:176 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:179 msgid "Attendee email" -msgstr "E-Mail Teilnehmer*in" +msgstr "E-Mail Teilnehmer" #: pretix/base/exporters/orderlist.py:609 pretix/base/models/vouchers.py:312 #: pretix/control/templates/pretixcontrol/vouchers/bulk.html:5 @@ -3593,7 +3593,7 @@ msgstr "Bitte wähle einen gültigen Staat aus." #: pretix/base/modelimport_orders.py:325 pretix/control/forms/filter.py:651 msgid "Attendee email address" -msgstr "Teilnehmer*innen-E-Mail-Adresse" +msgstr "Teilnehmer-E-Mail-Adresse" #: pretix/base/modelimport_orders.py:341 pretix/base/modelimport_orders.py:352 #: pretix/base/modelimport_orders.py:363 pretix/base/modelimport_orders.py:374 @@ -3605,7 +3605,7 @@ msgstr "Teilnehmer*innen-E-Mail-Adresse" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:197 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:200 msgid "Attendee address" -msgstr "Teilnehmer*innen-Adresse" +msgstr "Teilnehmer-Adresse" #: pretix/base/modelimport_orders.py:409 msgid "State" @@ -7322,7 +7322,7 @@ msgstr "Max Mustermann" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:186 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:189 msgid "Attendee company" -msgstr "Teilnehmer*innen-Firma" +msgstr "Teilnehmer-Firma" #: pretix/base/pdf.py:178 pretix/base/pdf.py:336 #: pretix/base/services/tickets.py:119 pretix/control/views/pdf.py:111 @@ -7331,7 +7331,7 @@ msgstr "Musterfirma" #: pretix/base/pdf.py:182 msgid "Full attendee address" -msgstr "Volle Teilnehmer*innen-Adresse" +msgstr "Volle Teilnehmer-Adresse" #: pretix/base/pdf.py:183 msgid "" @@ -7349,23 +7349,23 @@ msgstr "" #: pretix/base/pdf.py:187 msgid "Attendee street" -msgstr "Teilnehmer*innen-Straße" +msgstr "Teilnehmer-Straße" #: pretix/base/pdf.py:192 msgid "Attendee ZIP code" -msgstr "Teilnehmer*innen-PLZ" +msgstr "Teilnehmer-PLZ" #: pretix/base/pdf.py:197 msgid "Attendee city" -msgstr "Teilnehmer*innen-Stadt" +msgstr "Teilnehmer-Stadt" #: pretix/base/pdf.py:202 msgid "Attendee state" -msgstr "Teilnehmer*innen-Bundesstaat" +msgstr "Teilnehmer-Bundesstaat" #: pretix/base/pdf.py:207 msgid "Attendee country" -msgstr "Teilnehmer*innen-Land" +msgstr "Teilnehmer-Land" #: pretix/base/pdf.py:219 msgid "Pseudonymization ID (lead scanning)" @@ -7648,7 +7648,7 @@ msgstr "Herr Mustermann" #: pretix/plugins/ticketoutputpdf/exporters.py:99 #, python-brace-format msgid "Attendee name: {part}" -msgstr "Teilnehmer*innenname: {part}" +msgstr "Teilnehmer: {part}" #: pretix/base/pdf.py:671 msgid "Invoice address name for salutation" @@ -8317,7 +8317,7 @@ msgstr "Veranstaltungsort: {location}" #, python-brace-format msgctxt "invoice" msgid "Attendee: {name}" -msgstr "Teilnehmer*in: {name}" +msgstr "Teilnehmer: {name}" #: pretix/base/services/invoices.py:254 pretix/plugins/reports/exporters.py:298 msgctxt "subevent" @@ -9114,7 +9114,7 @@ msgstr "" #: pretix/base/settings.py:338 msgid "Hide prices on attendee ticket page" -msgstr "Preise auf Teilnehmer*innen-Ticket-Seite verstecken" +msgstr "Preise auf Teilnehmer-Ticket-Seite verstecken" #: pretix/base/settings.py:339 msgid "" @@ -9124,13 +9124,13 @@ msgid "" "price." msgstr "" "Wenn eine Person mehrere Tickets erwirbt und E-Mails an alle " -"Teilnehmer*innen verschickt werden, wird mit dieser Option der Ticketpreis " -"auf der Ticket-Seite der einzelnen Teilnehmer*innen versteckt. Nur die " +"Teilnehmer verschickt werden, wird mit dieser Option der Ticketpreis " +"auf der Ticket-Seite der einzelnen Teilnehmer versteckt. Nur die " "Person, welche die Tickets kauft, sieht den Preis." #: pretix/base/settings.py:357 msgid "Ask for attendee names" -msgstr "Namen der Teilnehmer*innen erfragen" +msgstr "Namen der Teilnehmer erfragen" #: pretix/base/settings.py:358 msgid "Ask for a name for all personalized tickets." @@ -9139,11 +9139,11 @@ msgstr "" #: pretix/base/settings.py:367 msgid "Require attendee names" -msgstr "Namen der Teilnehmer*innen erfordern" +msgstr "Namen der Teilnehmer erfordern" #: pretix/base/settings.py:368 msgid "Require customers to fill in the names of all attendees." -msgstr "Erfordere die Eingabe aller Teilnehmer*innen-Namen." +msgstr "Erfordere die Eingabe aller Teilnehmer-Namen." #: pretix/base/settings.py:378 msgid "Ask for email addresses per ticket" @@ -9165,7 +9165,7 @@ msgstr "" "aktivierst, fragt das System zusätzlich nach einzelnen E-Mail-Adressen für " "jedes personalisierte Ticket in der Bestellung. Dies könnte z.B. nützlich " "sein, wenn du auch im Falle von Gruppenbestellungen individuelle Adressen " -"von jeder Teilnehmer*in benötigst. pretix sendet die Bestellbestätigung " +"von jedem Teilnehmer benötigst. pretix sendet die Bestellbestätigung " "standardmäßig nach wie vor nur an die primäre Adresse, dies kann jedoch in " "den E-Mail-Einstellungen angepasst werden." @@ -9638,8 +9638,8 @@ msgid "" "but no indication of missing payment will be visible on the ticket pages of " "attendees who did not buy the ticket themselves." msgstr "" -"Die Box mit Zahlungsinstruktionen wird Ticketkäufer*innen weiter angezeigt, " -"aber Teilnehmer*innen, die ihr Ticket nicht selbst gekauft haben, werden " +"Die Box mit Zahlungsinstruktionen wird Ticketkäufern weiter angezeigt, " +"aber Teilnehmer, die ihr Ticket nicht selbst gekauft haben, werden " "keine Anzeichen des fehlenden Zahlungseingangs sehen." #: pretix/base/settings.py:996 @@ -10077,7 +10077,7 @@ msgstr "" #: pretix/base/settings.py:1509 msgid "Show number of check-ins to customer" -msgstr "Zeige Anzahl der Check-ins für Kund*innen an" +msgstr "Zeige Anzahl der Check-ins für Kunden an" #: pretix/base/settings.py:1510 msgid "" @@ -10088,12 +10088,12 @@ msgid "" "failed scans will not be counted, and the user will not see the different " "check-in lists." msgstr "" -"Wenn diese Option aktiv ist, können Kund*innen selbst sehen, wie oft sie die " +"Wenn diese Option aktiv ist, können Kunden selbst sehen, wie oft sie die " "Veranstaltung betreten haben. Das ist normalerweise nicht nötig, aber kann " "nützlich sein, wenn es Tickets gibt, die eine bestimmte Anzahl an Eintritten " -"erlauben, sodass Kund*innen die bisherige Nutzung des Tickets einsehen " +"erlauben, sodass Kunden die bisherige Nutzung des Tickets einsehen " "können. Ausgänge oder fehlgeschlagene Scans werden nicht angezeigt und die " -"Kund*innen sehen keine Aufschlüsselung verschiedener Check-in-Listen." +"Kunden sehen keine Aufschlüsselung verschiedener Check-in-Listen." #: pretix/base/settings.py:1523 msgid "Allow users to download tickets" @@ -10274,7 +10274,7 @@ msgstr "" #: pretix/base/settings.py:1686 pretix/base/settings.py:1695 msgid "Both the attendee and the person who ordered can make changes" msgstr "" -"Sowohl Besteller*in als auch Teilnehmer*innen können Änderungen vornehmen" +"Sowohl Besteller als auch Teilnehmer können Änderungen vornehmen" #: pretix/base/settings.py:1690 msgid "Allow customers to modify their information" @@ -10382,7 +10382,7 @@ msgstr "" #: pretix/base/settings.py:1796 msgid "Allow individual attendees to change their ticket" -msgstr "Erlaubt einzelnen Teilnehmer*innen ihr Ticket zu ändern" +msgstr "Erlaubt einzelnen Teilnehmer ihr Ticket zu ändern" #: pretix/base/settings.py:1797 msgid "" @@ -10394,7 +10394,7 @@ msgid "" msgstr "" "Standardmäßig kann nur die Person, welche die Tickets gekauft hat, " "Änderungen an der Bestellung vornehmen. Wenn diese Option aktiv ist, können " -"auch einzelne Teilnehmer*innen Änderungen vornehmen. Teilnehmer*innen können " +"auch einzelne Teilnehmer Änderungen vornehmen. Teilnehmer können " "jedoch immer nur Änderungen vornehmen, welche die Gesamtkosten der " "Bestellung nicht verändern. Solche Änderungen können nur vom Ticketkäufer " "vorgenommen werden." @@ -10578,7 +10578,7 @@ msgstr "Kontakt-E-Mail" #: pretix/base/settings.py:2032 pretix/control/forms/event.py:1708 msgid "We'll show this publicly to allow attendees to contact you." msgstr "" -"Wir werden diese Adresse veröffentlichen um Teilnehmer*innen zu ermöglichen, " +"Wir werden diese Adresse veröffentlichen um Teilnehmern zu ermöglichen, " "dich zu kontaktieren." #: pretix/base/settings.py:2040 pretix/control/forms/event.py:1700 @@ -10660,7 +10660,7 @@ msgid "" "people." msgstr "" "Du kannst dieses Feld benutzen um zusätzliche Informationen mit deinen " -"Teilnehmer*innen zu teilen, wie z.B. Anreise-Informationen oder den Link zu " +"Teilnehmer zu teilen, wie z.B. Anreise-Informationen oder den Link zu " "einer digitalen Veranstaltung. Wenn das Feld leer ist, fügen wir automatisch " "einen Link zum Ticketshop, die Einlass-Uhrzeit und den Veranstalter hier " "ein. Es sind keine Platzhalter mit sensiblen personenbezogenen Daten " @@ -10900,8 +10900,8 @@ msgstr "" "Diese Datei wird an die erste E-Mail angehängt, die wir beim Eingang einer " "neuen Bestellung verschicken. Sie kann daher mit den Textvorlagen " "\"Getätigte Bestellung\", \"Kostenlose Bestellung\" oder \"Erhaltene " -"Bestellung\" von oben auftreten. Sie wird ggf. sowohl an Besteller*innen als " -"auch Teilnehmer*innen verschickt. Nicht geeignet zum Versand nicht-" +"Bestellung\" von oben auftreten. Sie wird ggf. sowohl an Besteller als " +"auch Teilnehmer verschickt. Nicht geeignet zum Versand nicht-" "öffentlicher Informationen, da die Datei unabhängig davon verschickt wird, " "ob die Bestellung bezahlt oder freigegeben ist. Um zu vermeiden, dass diese " "wichtige E-Mail nicht ankommt, können nur PDF-Dateien mit maximal {size} MB " @@ -12102,7 +12102,7 @@ msgstr "" msgid "" "You cannot require specifying attendee names if you do not ask for them." msgstr "" -"Du kannst die Angabe von Teilnehmer*innennamen nur erfordern, wenn auch nach " +"Du kannst die Angabe von Teilnehmernamen nur erfordern, wenn auch nach " "Namen gefragt wird." #: pretix/base/settings.py:3805 @@ -13578,11 +13578,11 @@ msgstr "Ticket-Downloads" #: pretix/control/forms/event.py:1690 msgid "Your customers will be able to download their tickets in PDF format." msgstr "" -"Die Teilnehmer*innen werden ihre Tickets im PDF-Format herunterladen können." +"Die Teilnehmer werden ihre Tickets im PDF-Format herunterladen können." #: pretix/control/forms/event.py:1694 msgid "Require all attendees to fill in their names" -msgstr "Erfordere, dass alle Teilnehmer*innen ihre Namen ausfüllen" +msgstr "Erfordere, dass alle Teilnehmer ihre Namen ausfüllen" #: pretix/control/forms/event.py:1695 msgid "" @@ -13618,7 +13618,7 @@ msgid "" "then import your bank statements to process the payments within pretix, or " "mark them as paid manually." msgstr "" -"Deine Teilnehmer*innen werden angewiesen, das Geld direkt auf dein Bankkonto " +"Deine Teilnehmer werden angewiesen, das Geld direkt auf dein Bankkonto " "zu überweisen. Du kannst dann deinen Kontoauszug in pretix importieren, um " "Zahlungen zuzuweisen, oder die Bestellungen manuell als bezahlt markieren." @@ -13962,7 +13962,7 @@ msgstr "Check-in-Status" #: pretix/control/forms/filter.py:1888 #: pretix/plugins/checkinlists/exporters.py:107 msgid "All attendees" -msgstr "Alle Teilnehmer*innen" +msgstr "Alle Teilnehmer" #: pretix/control/forms/filter.py:1889 #: pretix/control/templates/pretixcontrol/checkin/index.html:183 @@ -14532,7 +14532,7 @@ msgid "" "people over 65. This ticket includes access to all parts of the event, " "except the VIP area." msgstr "" -"z.B. Dieses reduzierte Ticket ist erhältlich für Vollzeitstudent*innen, " +"z.B. Dieses reduzierte Ticket ist erhältlich für Vollzeitstudenten, " "Arbeitslose und Menschen über 65. Das Ticket enthält Zugang zu allen Teilen " "der Veranstaltung außer des VIP-Bereiches." @@ -16116,7 +16116,7 @@ msgstr "Eine individuelle E-Mail wurde verschickt." #: pretix/control/logdisplay.py:479 msgid "A custom email has been sent to an attendee." -msgstr "Eine individuelle E-Mail wurde an eine Teilnehmer*in verschickt." +msgstr "Eine individuelle E-Mail wurde an eine Teilnehmer verschickt." #: pretix/control/logdisplay.py:480 msgid "" @@ -17765,7 +17765,7 @@ msgstr "Terminal-ID" #: pretix/control/templates/pretixcontrol/boxoffice/payment.html:104 msgid "Card holder" -msgstr "Karteninhaber*in" +msgstr "Karteninhaber" #: pretix/control/templates/pretixcontrol/boxoffice/payment.html:108 msgid "Card expiration" @@ -18060,7 +18060,7 @@ msgstr "CSV" #: pretix/control/templates/pretixcontrol/checkin/index.html:73 msgid "No attendee record was found." -msgstr "Keine passenden Teilnehmer*innen gefunden." +msgstr "Keine passenden Teilnehmer gefunden." #: pretix/control/templates/pretixcontrol/checkin/index.html:91 #: pretix/control/templates/pretixcontrol/orders/index.html:128 @@ -19581,7 +19581,7 @@ msgid "" "provide ways for your attendees to contact you:" msgstr "" "Wenn irgendetwas schiefgeht oder unklar ist, empfehlen wir, dass du deinen " -"Teilnehmer*innen die Möglichkeit gibst, dich zu benachrichtigen:" +"Teilnehmer die Möglichkeit gibst, dich zu benachrichtigen:" #: pretix/control/templates/pretixcontrol/event/settings.html:7 #: pretix/control/templates/pretixcontrol/event/settings.html:13 @@ -20536,7 +20536,7 @@ msgid "" "Only purchases of such products will be considered \"attendees\" for most " "statistical purposes or within some plugins." msgstr "" -"Nur Käufe eines solchen Produkts werden als \"Teilnehmer*innen\" gewertet, " +"Nur Käufe eines solchen Produkts werden als \"Teilnehmer\" gewertet, " "z.B. in Statistiken oder in Funktionen von Erweiterungen." #: pretix/control/templates/pretixcontrol/item/create.html:39 @@ -20615,7 +20615,7 @@ msgid "" "The system will not ask for a name or other attendee details. This only " "affects system-provided fields, you can still add your own questions." msgstr "" -"Das System wird nicht nach einem Namen oder anderen Teilnehmer*innen-Daten " +"Das System wird nicht nach einem Namen oder anderen Teilnehmer-Daten " "fragen. Dies betrifft nur vom System bereitgestellte Felder, eigene Fragen " "können trotzdem hinzugefügt werden." @@ -21285,9 +21285,9 @@ msgid "" "ticket. If you provide food, one example might be to ask your users about " "dietary requirements." msgstr "" -"Fragen erlauben deinen Besucher*innen, zusätzliche Informationen zu ihrem " +"Fragen erlauben deinen Besucher, zusätzliche Informationen zu ihrem " "Ticket auszufüllen. Wenn deine Veranstaltung Verpflegung beinhaltet, " -"könntest du z.B. nach Allergien deiner Teilnehmer*innen fragen." +"könntest du z.B. nach Allergien deiner Teilnehmer fragen." #: pretix/control/templates/pretixcontrol/items/questions.html:14 msgid "Create a new question" @@ -21426,7 +21426,7 @@ msgstr "" "Um deine Produkte verfügbar zu machen, musst du Kontingente anlegen. " "Kontingente definieren, wie oft ein Produkt verkauft werden darf. Auf diese " "Art kannst du konfigurieren, ob deine Veranstaltung unbegrenzt viele " -"Teilnehmer*innen aufnehmen kann oder ob die Anzahl begrenzt ist. Du kannst " +"Teilnehmer aufnehmen kann oder ob die Anzahl begrenzt ist. Du kannst " "ein Produkt zu mehreren Kontingenten hinzufügen, um komplexere Anforderungen " "abzubilden, z.B. wenn du die Gesamtzahl der Tickets begrenzen willst, aber " "einen speziellen Ticket-Typ noch stärker begrenzen willst." @@ -22750,7 +22750,7 @@ msgstr "Sonstige Datenexporte" #: pretix/control/templates/pretixcontrol/orders/export.html:104 #: pretix/control/templates/pretixcontrol/organizers/export.html:104 msgid "Recommended for new users" -msgstr "Empfohlen für neue Benutzer*innen" +msgstr "Empfohlen für neue Benutzer" #: pretix/control/templates/pretixcontrol/orders/export_delete.html:4 #: pretix/control/templates/pretixcontrol/orders/export_delete.html:6 @@ -23713,7 +23713,7 @@ msgstr "Domains" #: pretix/control/templates/pretixcontrol/organizers/edit.html:301 msgid "This dialog is intended for advanced users." -msgstr "Dieser Dialog ist für fortgeschrittene Anwender*innen gedacht." +msgstr "Dieser Dialog ist für fortgeschrittene Anwender gedacht." #: pretix/control/templates/pretixcontrol/organizers/edit.html:302 msgid "" @@ -25857,7 +25857,7 @@ msgid "" "customers. This way, customers will not be able to discover the waiting list." msgstr "" "Entsprechend deiner Veranstaltungseinstellungen werden ausverkaufte Produkte " -"nicht angezeigt. Dies führt dazu, dass Kund*innen die Warteliste nicht " +"nicht angezeigt. Dies führt dazu, dass Kunden die Warteliste nicht " "finden können." #: pretix/control/templates/pretixcontrol/waitinglist/index.html:36 @@ -28106,7 +28106,7 @@ msgstr "PDF-Sammlungen" #: pretix/plugins/badges/exporters.py:423 msgid "Download all attendee badges as one large PDF for printing." -msgstr "Alle Teilnehmer*innen-Badges in einer großen PDF-Datei für den Druck." +msgstr "Alle Teilnehmer-Badges in einer großen PDF-Datei für den Druck." #: pretix/plugins/badges/exporters.py:444 #: pretix/plugins/ticketoutputpdf/exporters.py:80 @@ -28361,7 +28361,7 @@ msgstr "Anderes Bankkonto" #: pretix/plugins/banktransfer/payment.py:91 msgid "Name of account holder" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/banktransfer/payment.py:93 msgid "" @@ -28554,7 +28554,7 @@ msgstr "Bitte überweise den vollen Betrag auf das folgende Bankkonto:" #: pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_confirm.html:32 #: pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_confirm.html:35 msgid "Account holder" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/banktransfer/payment.py:468 #: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_confirm.html:17 @@ -29266,7 +29266,7 @@ msgid "" "Download a spreadsheet with all attendees that are included in a check-in " "list." msgstr "" -"Tabelle (Excel oder CSV) mit allen Teilnehmer*innen, die in einer Check-in-" +"Tabelle (Excel oder CSV) mit allen Teilnehmer, die in einer Check-in-" "Liste zutrittsberechtigt sind." #: pretix/plugins/checkinlists/exporters.py:497 @@ -30452,7 +30452,7 @@ msgstr "Geplante E-Mails" #: pretix/plugins/sendmail/signals.py:121 msgid "Mass email was sent to customers or attendees." -msgstr "Rundmail wurde an Kunden oder Teilnehmer*innen verschickt." +msgstr "Rundmail wurde an Kunden oder Teilnehmer verschickt." #: pretix/plugins/sendmail/signals.py:122 msgid "Mass email was sent to waiting list entries." @@ -30480,7 +30480,7 @@ msgstr "Eine automatisierte E-Mail wurde an den Besteller verschickt" #: pretix/plugins/sendmail/signals.py:136 msgid "A scheduled email was sent to a ticket holder" -msgstr "Eine automatisierte E-Mail wurde an eine Teilnehmer*in verschickt." +msgstr "Eine automatisierte E-Mail wurde an einen Teilnehmer verschickt." #: pretix/plugins/sendmail/signals.py:137 msgid "An email rule was deleted" @@ -30513,7 +30513,7 @@ msgstr "Alle nicht eingecheckten Kunden" #: pretix/plugins/sendmail/templates/pretixplugins/sendmail/history_fragment_orders.html:23 msgid "Attendee contact addresses" -msgstr "Teilnehmer*innen-E-Mail-Adressen" +msgstr "Teilnehmer-E-Mail-Adressen" #: pretix/plugins/sendmail/templates/pretixplugins/sendmail/history_fragment_orders.html:25 msgid "All contact addresses" @@ -30677,14 +30677,14 @@ msgstr "" #: pretix/plugins/sendmail/views.py:250 msgid "Orders or attendees" -msgstr "Bestellungen oder Teilnehmer*innen" +msgstr "Bestellungen oder Teilnehmer" #: pretix/plugins/sendmail/views.py:251 msgid "" "Send an email to every customer, or to every person a ticket has been " "purchased for, or a combination of both." msgstr "" -"Sende eine E-Mail an alle Ticketkäufer*innen, alle Ticketinhaber*innen oder " +"Sende eine E-Mail an alle Ticketkäufer, alle Ticketinhaber oder " "eine Kombination aus beiden Gruppen." #: pretix/plugins/sendmail/views.py:417 @@ -31205,23 +31205,23 @@ msgstr "SEPA-Lastschrift" #: pretix/plugins/stripe/payment.py:1232 msgid "Account Holder Name" -msgstr "Kontoinhaber*in" +msgstr "Kontoinhaber" #: pretix/plugins/stripe/payment.py:1237 msgid "Account Holder Street" -msgstr "Straße (Kontoinhaber*in)" +msgstr "Straße (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1249 msgid "Account Holder Postal Code" -msgstr "PLZ (Kontoinhaber*in)" +msgstr "PLZ (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1261 msgid "Account Holder City" -msgstr "Stadt (Kontoinhaber*in)" +msgstr "Stadt (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1273 msgid "Account Holder Country" -msgstr "Land (Kontoinhaber*in)" +msgstr "Land (Kontoinhaber)" #: pretix/plugins/stripe/payment.py:1317 msgid "Affirm via Stripe" @@ -34618,12 +34618,12 @@ msgstr "Möchtest das folgende Profil wirklich aus deinem Kundenkonto löschen?" #: pretix/presale/templates/pretixpresale/organizers/customer_profiles.html:11 #: pretix/presale/views/customer.py:378 msgid "Attendee profiles" -msgstr "Teilnehmer*innen-Adresse" +msgstr "Teilnehmer-Adresse" #: pretix/presale/templates/pretixpresale/organizers/customer_profiles.html:37 msgid "You don’t have any attendee profiles in your account yet." msgstr "" -"In deinem Kundenkonto sind noch keine Teilnehmer*innen-Profile gespeichert." +"In deinem Kundenkonto sind noch keine Teilnehmer-Profile gespeichert." #: pretix/presale/templates/pretixpresale/organizers/customer_registration.html:6 msgid "Registration" @@ -35621,7 +35621,7 @@ msgstr "Kosovo" #~ "This plugin allows you to generate badges or name tags for your attendees." #~ msgstr "" #~ "Diese Erweiterung erlaubt, Namensschilder oder Badges für die " -#~ "Teilnehmer*innen zu erstellen." +#~ "Teilnehmer zu erstellen." #~ msgid "This plugin allows you to receive payments via PayPal" #~ msgstr "Dieses Plugin erlaubt, Zahlungen über PayPal anzunehmen" @@ -36205,7 +36205,7 @@ msgstr "Kosovo" #~ msgstr "Biete Ticket-Download bereits vor Bezahlung einer Bestellung an" #~ msgid "Attendee names" -#~ msgstr "Teilnehmer*innennamen" +#~ msgstr "Teilnehmername" #~ msgid "Enable output" #~ msgstr "Aktivieren" @@ -36488,7 +36488,7 @@ msgstr "Kosovo" #~ "If checked, users can cancel orders by themselves as long as they are not " #~ "yet paid." #~ msgstr "" -#~ "Wenn diese Option aktiviert ist, können Teilnehmer*innen selbstständig " +#~ "Wenn diese Option aktiviert ist, können Teilnehmer selbstständig " #~ "Bestellungen stornieren solange sie nicht bezahlt wurden." #~ msgid "Sales overview" From 9179621e72bbbc54ce835d9a37a07c4cea98d709 Mon Sep 17 00:00:00 2001 From: UpdateBot Date: Wed, 5 Feb 2025 22:02:20 +0100 Subject: [PATCH 02/10] Use latest tag in master branch --- .gitea/workflows/cicd.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/cicd.yaml b/.gitea/workflows/cicd.yaml index 3ddc71a06..877d6f721 100644 --- a/.gitea/workflows/cicd.yaml +++ b/.gitea/workflows/cicd.yaml @@ -13,6 +13,6 @@ jobs: - name: Login to Docker Registry run: podman login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_TOKEN }} cr.ortlerstrasse.de - name: Build Docker image - run: podman build -t cr.ortlerstrasse.de/cgo/pretix:2025.1.0 . + run: podman build -t cr.ortlerstrasse.de/cgo/pretix:latest . - name: Push Docker image - run: podman push cr.ortlerstrasse.de/cgo/pretix:2025.1.0 \ No newline at end of file + run: podman push cr.ortlerstrasse.de/cgo/pretix:latest \ No newline at end of file From 931ba73f1df42f798f22ad6576c1300080725342 Mon Sep 17 00:00:00 2001 From: UpdateBot Date: Mon, 10 Feb 2025 15:47:21 +0100 Subject: [PATCH 03/10] Furhter text udpates --- src/pretix/locale/de/LC_MESSAGES/django.po | 6 +++--- src/pretix/locale/de_Informal/LC_MESSAGES/django.po | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pretix/locale/de/LC_MESSAGES/django.po b/src/pretix/locale/de/LC_MESSAGES/django.po index cec389753..eb09c41b8 100644 --- a/src/pretix/locale/de/LC_MESSAGES/django.po +++ b/src/pretix/locale/de/LC_MESSAGES/django.po @@ -26224,11 +26224,11 @@ msgstr "Das ausgewählte List wurde gelöscht." #: pretix/control/views/dashboards.py:115 msgid "Attendees (ordered)" -msgstr "Teilnehmende (bestellt)" +msgstr "Teilnehmer (bestellt)" #: pretix/control/views/dashboards.py:125 msgid "Attendees (paid)" -msgstr "Teilnehmende (bezahlt)" +msgstr "Teilnehmer (bezahlt)" #: pretix/control/views/dashboards.py:137 #, python-brace-format @@ -33039,7 +33039,7 @@ msgstr[1] "Das Ticket wurde %(count)s-mal eingelöst." #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:170 msgid "No attendee name provided" -msgstr "Name der teilnehmenden Person nicht angegeben" +msgstr "Name des Teilnehmenrs nicht angegeben" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:223 msgid "The image you previously uploaded" diff --git a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po index 0b29b757f..aef6f1fa5 100644 --- a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po +++ b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po @@ -32980,7 +32980,7 @@ msgstr[1] "Das Ticket wurde %(count)s-mal eingelöst." #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:170 msgid "No attendee name provided" -msgstr "Name der teilnehmenden Person nicht angegeben" +msgstr "Name des Teilnehmenrs nicht angegeben" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:223 msgid "The image you previously uploaded" From 38abad0bf6133f330ac48d87bd9b4ee244f18b07 Mon Sep 17 00:00:00 2001 From: UpdateBot Date: Tue, 11 Feb 2025 20:44:55 +0100 Subject: [PATCH 04/10] Update dockerbuild, use Tag if a tag was pushed, latest otherwise --- .gitea/workflows/cicd.yaml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/cicd.yaml b/.gitea/workflows/cicd.yaml index 877d6f721..3f41c6b67 100644 --- a/.gitea/workflows/cicd.yaml +++ b/.gitea/workflows/cicd.yaml @@ -1,7 +1,7 @@ name: Build Deploy email notification tool run-name: ${{ gitea.actor }} building new version of the email notification tool on: - push: + push: # Baut bei jedem Push (Branches + Tags) workflow_dispatch: jobs: @@ -10,9 +10,20 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v3 + - name: Login to Docker Registry run: podman login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_TOKEN }} cr.ortlerstrasse.de + + - name: Set Docker Image Tag + run: | + if [[ "${{ gitea.ref }}" == refs/tags/* ]]; then + echo "TAG_NAME=${{ gitea.ref_name }}" >> $GITHUB_ENV + else + echo "TAG_NAME=latest" >> $GITHUB_ENV + fi + - name: Build Docker image - run: podman build -t cr.ortlerstrasse.de/cgo/pretix:latest . + run: podman build -t cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }} . + - name: Push Docker image - run: podman push cr.ortlerstrasse.de/cgo/pretix:latest \ No newline at end of file + run: podman push cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }} \ No newline at end of file From 82366dd6c9331acd15a0dd8920b9e8ee779a8799 Mon Sep 17 00:00:00 2001 From: UpdateBot Date: Tue, 11 Feb 2025 20:48:27 +0100 Subject: [PATCH 05/10] Add debugging Information --- .gitea/workflows/cicd.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/cicd.yaml b/.gitea/workflows/cicd.yaml index 3f41c6b67..fe5c81d1c 100644 --- a/.gitea/workflows/cicd.yaml +++ b/.gitea/workflows/cicd.yaml @@ -26,4 +26,6 @@ jobs: run: podman build -t cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }} . - name: Push Docker image - run: podman push cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }} \ No newline at end of file + run: | + podman push cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }} + echo "Image pushed successfully: cr.ortlerstrasse.de/cgo/pretix:${{ env.TAG_NAME }}" \ No newline at end of file From 34efc2d953fbda66de426891ad2d85126b9fbee2 Mon Sep 17 00:00:00 2001 From: Philipp Kern Date: Tue, 11 Feb 2025 23:56:55 +0100 Subject: [PATCH 06/10] Add relevant_orderlist exporter (including bugfixes) This Exporter has the most useful information in the first rows of the exported document. Specifically the product and the custom questions. Other fields are also resorted somewhat to place very useless columns at the end of the table. See code for details :) - register relevant_orderlist as separate data_exporter - sort it with the other order data exporters. --- src/pretix/base/exporters/__init__.py | 1 + src/pretix/base/exporters/orderlist.py | 2 +- .../base/exporters/relevant_orderlist.py | 1199 +++++++++++++++++ src/pretix/locale/de/LC_MESSAGES/django.po | 16 + 4 files changed, 1217 insertions(+), 1 deletion(-) create mode 100644 src/pretix/base/exporters/relevant_orderlist.py diff --git a/src/pretix/base/exporters/__init__.py b/src/pretix/base/exporters/__init__.py index 420741db6..49c8b6437 100644 --- a/src/pretix/base/exporters/__init__.py +++ b/src/pretix/base/exporters/__init__.py @@ -28,5 +28,6 @@ from .items import * # noqa from .json import * # noqa from .mail import * # noqa from .orderlist import * # noqa +from .relevant_orderlist import * # noqa from .reusablemedia import * # noqa from .waitinglist import * # noqa diff --git a/src/pretix/base/exporters/orderlist.py b/src/pretix/base/exporters/orderlist.py index 887115772..610074f54 100644 --- a/src/pretix/base/exporters/orderlist.py +++ b/src/pretix/base/exporters/orderlist.py @@ -88,7 +88,7 @@ class OrderListExporter(MultiSheetListExporter): description = gettext_lazy('Download a spreadsheet of all orders. The spreadsheet will include three sheets, one ' 'with a line for every order, one with a line for every order position, and one with ' 'a line for every additional fee charged in an order.') - featured = True + featured = False @cached_property def providers(self): diff --git a/src/pretix/base/exporters/relevant_orderlist.py b/src/pretix/base/exporters/relevant_orderlist.py new file mode 100644 index 000000000..a0e2355f7 --- /dev/null +++ b/src/pretix/base/exporters/relevant_orderlist.py @@ -0,0 +1,1199 @@ +# +# This file is part of pretix (Community Edition). +# +# Copyright (C) 2014-2020 Raphael Michel and contributors +# Copyright (C) 2020-2021 rami.io GmbH and contributors +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General +# Public License as published by the Free Software Foundation in version 3 of the License. +# +# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are +# applicable granting you additional permissions and placing additional restrictions on your usage of this software. +# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive +# this file, see . +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along with this program. If not, see +# . +# + +# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of +# the Apache License 2.0 can be obtained at . +# +# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A +# full history of changes and contributors is available at . +# +# This file contains Apache-licensed contributions copyrighted by: Benjamin Hättasch, Tobias Kunze +# +# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under the License. + +from collections import OrderedDict, defaultdict +from decimal import Decimal +from zoneinfo import ZoneInfo + +from django import forms +from django.conf import settings +from django.db.models import ( + Case, + CharField, + Count, + DateTimeField, + F, + IntegerField, + Max, + Min, + OuterRef, + Q, + Subquery, + Sum, + When, +) +from django.db.models.functions import Coalesce +from django.dispatch import receiver +from django.utils.formats import date_format +from django.utils.functional import cached_property +from django.utils.timezone import get_current_timezone, now +from django.utils.translation import ( + gettext as _, + gettext_lazy, + pgettext, + pgettext_lazy, +) +from openpyxl.cell import WriteOnlyCell +from openpyxl.comments import Comment +from openpyxl.styles import Font, PatternFill + +from pretix.base.models import ( + Checkin, + GiftCard, + GiftCardTransaction, + Invoice, + InvoiceAddress, + Order, + OrderPosition, + Question, +) +from pretix.base.models.orders import ( + OrderFee, + OrderPayment, + OrderRefund, + Transaction, +) +from pretix.base.services.quotas import QuotaAvailability +from pretix.base.settings import PERSON_NAME_SCHEMES, get_name_parts_localized + +from ...control.forms.filter import get_all_payment_providers +from ...helpers import GroupConcat +from ...helpers.iter import chunked_iterable +from ...helpers.safe_openpyxl import remove_invalid_excel_chars +from ..exporter import ( + ListExporter, + MultiSheetListExporter, + OrganizerLevelExportMixin, +) +from ..forms.widgets import SplitDateTimePickerWidget +from ..signals import ( + register_data_exporters, + register_multievent_data_exporters, +) +from ..timeframes import ( + DateFrameField, + resolve_timeframe_to_datetime_start_inclusive_end_exclusive, +) + + +class RelevantOrderListExporter(MultiSheetListExporter): + identifier = "relevantorderlist" + verbose_name = gettext_lazy("Order data (sorted by relevance)") + category = pgettext_lazy("export_category", "Order data") + description = gettext_lazy( + "Download a spreadsheet of all orders. The spreadsheet will include three sheets, one " + "with a line for every order, one with a line for every order position, and one with " + "a line for every additional fee charged in an order. The most relevant data is in the " + "first columns of the tables." + ) + featured = True + + @cached_property + def providers(self): + return dict(get_all_payment_providers()) + + @property + def sheets(self): + return ( + ("orders", _("Orders")), + ("positions", _("Order positions")), + ("fees", _("Order fees")), + ) + + @property + def additional_form_fields(self): + d = [ + ( + "paid_only", + forms.BooleanField( + label=_("Only paid orders"), initial=False, required=False + ), + ), + ( + "include_payment_amounts", + forms.BooleanField( + label=_("Include payment amounts"), initial=True, required=False + ), + ), + ( + "group_multiple_choice", + forms.BooleanField( + label=_("Show multiple choice answers grouped in one column"), + initial=False, + required=False, + ), + ), + ( + "date_range", + DateFrameField( + label=_("Date range"), + include_future_frames=False, + required=False, + help_text=_("Only include orders created within this date range."), + ), + ), + ( + "event_date_range", + DateFrameField( + label=_("Event date"), + include_future_frames=True, + required=False, + help_text=_( + "Only include orders including at least one ticket for a date in this range. " + "Will also include other dates in case of mixed orders!" + ), + ), + ), + ] + d = OrderedDict(d) + if not self.is_multievent and not self.event.has_subevents: + del d["event_date_range"] + return d + + def _get_all_payment_methods(self, qs): + pps = dict(get_all_payment_providers()) + return sorted( + [ + (pp, pps[pp]) + for pp in set( + OrderPayment.objects.exclude(provider="free") + .filter(order__event__in=self.events) + .values_list("provider", flat=True) + .distinct() + ) + ], + key=lambda pp: pp[0], + ) + + def _get_all_tax_rates(self, qs): + tax_rates = set( + a + for a in OrderFee.objects.filter(order__event__in=self.events) + .values_list("tax_rate", flat=True) + .distinct() + .order_by() + ) + tax_rates |= set( + a + for a in OrderPosition.objects.filter(order__event__in=self.events) + .values_list("tax_rate", flat=True) + .distinct() + .order_by() + ) + tax_rates = sorted(tax_rates) + return tax_rates + + def iterate_sheet(self, form_data, sheet): + if sheet == "orders": + return self.iterate_orders(form_data) + elif sheet == "positions": + return self.iterate_positions(form_data) + elif sheet == "fees": + return self.iterate_fees(form_data) + + @cached_property + def event_object_cache(self): + return {e.pk: e for e in self.events} + + def _date_filter(self, qs, form_data, rel): + annotations = {} + filters = {} + + if form_data.get("date_range"): + dt_start, dt_end = ( + resolve_timeframe_to_datetime_start_inclusive_end_exclusive( + now(), form_data["date_range"], self.timezone + ) + ) + if dt_start: + filters[f"{rel}datetime__gte"] = dt_start + if dt_end: + filters[f"{rel}datetime__lt"] = dt_end + + if form_data.get("event_date_range"): + dt_start, dt_end = ( + resolve_timeframe_to_datetime_start_inclusive_end_exclusive( + now(), form_data["event_date_range"], self.timezone + ) + ) + if dt_start: + annotations["event_date_max"] = Case( + When( + **{f"{rel}event__has_subevents": True}, + then=Max(f"{rel}all_positions__subevent__date_from"), + ), + default=F(f"{rel}event__date_from"), + ) + filters["event_date_max__gte"] = dt_start + if dt_end: + annotations["event_date_min"] = Case( + When( + **{f"{rel}event__has_subevents": True}, + then=Min(f"{rel}all_positions__subevent__date_from"), + ), + default=F(f"{rel}event__date_from"), + ) + filters["event_date_min__lt"] = dt_end + + if filters: + return qs.annotate(**annotations).filter(**filters) + return qs + + def orders_qs(self, form_data): + p_date = ( + OrderPayment.objects.filter( + order=OuterRef("pk"), + state__in=( + OrderPayment.PAYMENT_STATE_CONFIRMED, + OrderPayment.PAYMENT_STATE_REFUNDED, + ), + payment_date__isnull=False, + ) + .values("order") + .annotate(m=Max("payment_date")) + .values("m") + .order_by() + ) + p_providers = ( + OrderPayment.objects.filter( + order=OuterRef("pk"), + state__in=( + OrderPayment.PAYMENT_STATE_CONFIRMED, + OrderPayment.PAYMENT_STATE_REFUNDED, + OrderPayment.PAYMENT_STATE_PENDING, + OrderPayment.PAYMENT_STATE_CREATED, + ), + ) + .values("order") + .annotate(m=GroupConcat("provider", delimiter=",")) + .values("m") + .order_by() + ) + i_numbers = ( + Invoice.objects.filter( + order=OuterRef("pk"), + ) + .values("order") + .annotate(m=GroupConcat("full_invoice_no", delimiter=", ")) + .values("m") + .order_by() + ) + + s = ( + OrderPosition.objects.filter(order=OuterRef("pk")) + .order_by() + .values("order") + .annotate(k=Count("id")) + .values("k") + ) + qs = ( + Order.objects.filter(event__in=self.events) + .annotate( + payment_date=Subquery(p_date, output_field=DateTimeField()), + payment_providers=Subquery(p_providers, output_field=CharField()), + invoice_numbers=Subquery(i_numbers, output_field=CharField()), + pcnt=Subquery(s, output_field=IntegerField()), + ) + .select_related("invoice_address", "customer") + ) + + qs = self._date_filter(qs, form_data, rel="") + + if form_data["paid_only"]: + qs = qs.filter(status=Order.STATUS_PAID) + return qs + + # Bestellungen (hier geht es hauptsächlich um die Beträge und ob sie bezahlt sind) + # Wichtig: Bestellnummer ("Order code"), Gesamtbetrag ("Order total"), Status ("Status"), + # E-Mail ("Email"), Name ("Name") + aufgeteilt, + # Bezahlt mit {Zahlungsmethode...} ("Payed by {method}") + # Semi-Wichtig: Datum der letzten Zahlung ("Date of last payment"), + # Zahlungsmethoden ("Payment providers") + # Unwichtig: alles andere + def iterate_orders(self, form_data: dict): + qs = self.orders_qs(form_data) + tax_rates = self._get_all_tax_rates(qs) + + # HEADERS START (Must be reordered the same way the Fields get reordered) + headers = [ + _("Order code"), # Wichtig + _("Order total"), # Wichtig + _("Status"), # Wichtig + _("Email"), # Wichtig + _("Name"), # Wichtig + ] + name_scheme = ( # für Wichtig + PERSON_NAME_SCHEMES[self.event.settings.name_scheme] + if not self.is_multievent + else None + ) + if name_scheme and len(name_scheme["fields"]) > 1: # Wichtig + for k, label, w in name_scheme["fields"]: + headers.append(label) + if form_data.get("include_payment_amounts"): # Wichtig + payment_methods = self._get_all_payment_methods(qs) + for id, vn in payment_methods: + headers.append(_("Paid by {method}").format(method=vn)) + + headers += [ + _("Date of last payment"), # Semi-Wichtig + _("Payment providers"), # Semi-Wichtig + _("Event slug"), + _("Event name"), + _("Phone number"), + _("Order date"), + _("Order time"), + _("Company"), + ] + headers += [ + _("Address"), + _("ZIP code"), + _("City"), + _("Country"), + pgettext("address", "State"), + _("Custom address field"), + _("VAT ID"), + _("Fees"), + _("Order locale"), + ] + + for tr in tax_rates: + headers += [ + _("Gross at {rate} % tax").format(rate=tr), + _("Net at {rate} % tax").format(rate=tr), + _("Tax value at {rate} % tax").format(rate=tr), + ] + + headers.append(_("Invoice numbers")) + headers.append(_("Sales channel")) + headers.append(_("Requires special attention")) + headers.append(_("Check-in text")) + headers.append(_("Comment")) + headers.append(_("Follow-up date")) + headers.append(_("Positions")) + headers.append(_("Email address verified")) + headers.append(_("External customer ID")) + + # get meta_data labels from first cached event + headers += next(iter(self.event_object_cache.values())).meta_data.keys() + yield headers + # HEADERS END + + full_fee_sum_cache = { + o["order__id"]: o["grosssum"] + for o in OrderFee.objects.values("tax_rate", "order__id") + .order_by() + .annotate(grosssum=Sum("value")) + } + fee_sum_cache = { + (o["order__id"], o["tax_rate"]): o + for o in OrderFee.objects.values("tax_rate", "order__id") + .order_by() + .annotate(taxsum=Sum("tax_value"), grosssum=Sum("value")) + } + if form_data.get("include_payment_amounts"): + payment_sum_cache = { + (o["order__id"], o["provider"]): o["grosssum"] + for o in OrderPayment.objects.values("provider", "order__id") + .order_by() + .filter( + state__in=[ + OrderPayment.PAYMENT_STATE_CONFIRMED, + OrderPayment.PAYMENT_STATE_REFUNDED, + ] + ) + .annotate(grosssum=Sum("amount")) + } + refund_sum_cache = { + (o["order__id"], o["provider"]): o["grosssum"] + for o in OrderRefund.objects.values("provider", "order__id") + .order_by() + .filter( + state__in=[ + OrderRefund.REFUND_STATE_DONE, + OrderRefund.REFUND_STATE_TRANSIT, + ] + ) + .annotate(grosssum=Sum("amount")) + } + sum_cache = { + (o["order__id"], o["tax_rate"]): o + for o in OrderPosition.objects.values("tax_rate", "order__id") + .order_by() + .annotate(taxsum=Sum("tax_value"), grosssum=Sum("price")) + } + + yield self.ProgressSetTotal(total=qs.count()) + for order in qs.order_by("datetime").iterator(): + tz = ZoneInfo(self.event_object_cache[order.event_id].settings.timezone) + + # ROW(S) START (Must be reordered the same way the Fields get reordered) + row = [ + order.code, # Wichtig ("Order code") + order.total, # Wichtig ("Order total") + order.get_extended_status_display(), # Wichtig ("Status") + order.email, # Wichtig ("Email") + ] + try: # Wichtig: ("Name") + aufgegeilt + row.append(order.invoice_address.name) + if name_scheme and len(name_scheme["fields"]) > 1: + for k, label, w in name_scheme["fields"]: + row.append( + get_name_parts_localized( + order.invoice_address.name_parts, k + ) + ) + except InvoiceAddress.DoesNotExist: + row += [""] * ( + 1 + + ( + len(name_scheme["fields"]) + if name_scheme and len(name_scheme["fields"]) > 1 + else 0 + ) + ) + + if form_data.get( + "include_payment_amounts" + ): # Wichtig ("Payed by {method}") + payment_methods = self._get_all_payment_methods(qs) + for id, vn in payment_methods: + row.append( + payment_sum_cache.get((order.id, id), Decimal("0.00")) + - refund_sum_cache.get((order.id, id), Decimal("0.00")) + ) + + row.append( # Semi-Wichtig ("Date of last payment") + order.payment_date.astimezone(tz).strftime("%Y-%m-%d") + if order.payment_date + else "" + ) + row.append( # Semi-Wichtig ("Payment providers") + ", ".join( + [ + str(self.providers.get(p, p)) + for p in sorted(set((order.payment_providers or "").split(","))) + if p and p != "free" + ] + ) + ) + + row += [ # unwichtig + self.event_object_cache[order.event_id].slug, + str(self.event_object_cache[order.event_id].name), + str(order.phone) if order.phone else "", + order.datetime.astimezone(tz).strftime("%Y-%m-%d"), + order.datetime.astimezone(tz).strftime("%H:%M:%S"), + ] + try: + row.append(order.invoice_address.company) + row += [ + order.invoice_address.street, + order.invoice_address.zipcode, + order.invoice_address.city, + ( + order.invoice_address.country + if order.invoice_address.country + else order.invoice_address.country_old + ), + order.invoice_address.state, + order.invoice_address.custom_field, + order.invoice_address.vat_id, + ] + except InvoiceAddress.DoesNotExist: + row += [""] * (8) + + row += [ + full_fee_sum_cache.get(order.id) or Decimal("0.00"), + order.locale, + ] + + for tr in tax_rates: + taxrate_values = sum_cache.get( + (order.id, tr), + {"grosssum": Decimal("0.00"), "taxsum": Decimal("0.00")}, + ) + fee_taxrate_values = fee_sum_cache.get( + (order.id, tr), + {"grosssum": Decimal("0.00"), "taxsum": Decimal("0.00")}, + ) + + row += [ + taxrate_values["grosssum"] + fee_taxrate_values["grosssum"], + ( + taxrate_values["grosssum"] + - taxrate_values["taxsum"] + + fee_taxrate_values["grosssum"] + - fee_taxrate_values["taxsum"] + ), + taxrate_values["taxsum"] + fee_taxrate_values["taxsum"], + ] + + row.append(order.invoice_numbers) + row.append(order.sales_channel) + row.append(_("Yes") if order.checkin_attention else _("No")) + row.append(order.checkin_text or "") + row.append(order.comment or "") + row.append( + order.custom_followup_at.strftime("%Y-%m-%d") + if order.custom_followup_at + else "" + ) + row.append(order.pcnt) + row.append(_("Yes") if order.email_known_to_work else _("No")) + row.append( + str(order.customer.external_identifier) + if order.customer and order.customer.external_identifier + else "" + ) + + row += self.event_object_cache[order.event_id].meta_data.values() + yield row + # ROW(S) END + + def fees_qs(self, form_data): + p_providers = ( + OrderPayment.objects.filter( + order=OuterRef("order"), + state__in=( + OrderPayment.PAYMENT_STATE_CONFIRMED, + OrderPayment.PAYMENT_STATE_REFUNDED, + OrderPayment.PAYMENT_STATE_PENDING, + OrderPayment.PAYMENT_STATE_CREATED, + ), + ) + .values("order") + .annotate(m=GroupConcat("provider", delimiter=",")) + .values("m") + .order_by() + ) + qs = ( + OrderFee.all.filter( + order__event__in=self.events, + ) + .annotate( + payment_providers=Subquery(p_providers, output_field=CharField()), + ) + .select_related( + "order", "order__invoice_address", "order__customer", "tax_rule" + ) + ) + if form_data["paid_only"]: + qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False) + + qs = self._date_filter(qs, form_data, rel="order__") + return qs + + # Gebühren, hier sind alle Felder irrelevant + def iterate_fees(self, form_data: dict): + qs = self.fees_qs(form_data) + + headers = [ + _("Event slug"), + _("Event name"), + _("Order code"), + _("Status"), + _("Email"), + _("Phone number"), + _("Order date"), + _("Order time"), + _("Fee type"), + _("Description"), + _("Price"), + _("Tax rate"), + _("Tax rule"), + _("Tax value"), + _("Company"), + _("Invoice address name"), + ] + name_scheme = ( + PERSON_NAME_SCHEMES[self.event.settings.name_scheme] + if not self.is_multievent + else None + ) + if name_scheme and len(name_scheme["fields"]) > 1: + for k, label, w in name_scheme["fields"]: + headers.append(_("Invoice address name") + ": " + str(label)) + headers += [ + _("Address"), + _("ZIP code"), + _("City"), + _("Country"), + pgettext("address", "State"), + _("VAT ID"), + ] + + headers.append(_("External customer ID")) + headers.append(_("Payment providers")) + + # get meta_data labels from first cached event + headers += next(iter(self.event_object_cache.values())).meta_data.keys() + yield headers + + yield self.ProgressSetTotal(total=qs.count()) + for op in qs.order_by("order__datetime").iterator(): + order = op.order + tz = ZoneInfo(order.event.settings.timezone) + row = [ + self.event_object_cache[order.event_id].slug, + str(self.event_object_cache[order.event_id].name), + order.code, + _("canceled") if op.canceled else order.get_extended_status_display(), + order.email, + str(order.phone) if order.phone else "", + order.datetime.astimezone(tz).strftime("%Y-%m-%d"), + order.datetime.astimezone(tz).strftime("%H:%M:%S"), + op.get_fee_type_display(), + op.description, + op.value, + op.tax_rate, + str(op.tax_rule) if op.tax_rule else "", + op.tax_value, + ] + try: + row += [ + order.invoice_address.company, + order.invoice_address.name, + ] + if name_scheme and len(name_scheme["fields"]) > 1: + for k, label, w in name_scheme["fields"]: + row.append( + get_name_parts_localized( + order.invoice_address.name_parts, k + ) + ) + row += [ + order.invoice_address.street, + order.invoice_address.zipcode, + order.invoice_address.city, + ( + order.invoice_address.country + if order.invoice_address.country + else order.invoice_address.country_old + ), + order.invoice_address.state, + order.invoice_address.vat_id, + ] + except InvoiceAddress.DoesNotExist: + row += [""] * ( + 8 + + ( + len(name_scheme["fields"]) + if name_scheme and len(name_scheme["fields"]) > 1 + else 0 + ) + ) + row.append( + str(order.customer.external_identifier) + if order.customer and order.customer.external_identifier + else "" + ) + row.append( + ", ".join( + [ + str(self.providers.get(p, p)) + for p in sorted(set((op.payment_providers or "").split(","))) + if p and p != "free" + ] + ) + ) + row += self.event_object_cache[order.event_id].meta_data.values() + yield row + + def positions_qs(self, form_data: dict): + qs = OrderPosition.all.filter( + order__event__in=self.events, + ) + if form_data["paid_only"]: + qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False) + + qs = self._date_filter(qs, form_data, rel="order__") + return qs + + # Bestellzeilen: Persönliche Daten, sehr viel Umsortieren ggü orderlist.py, deshalb TODO + def iterate_positions(self, form_data: dict): + base_qs = self.positions_qs(form_data) + + p_providers = ( + OrderPayment.objects.filter( + order=OuterRef("order"), + state__in=( + OrderPayment.PAYMENT_STATE_CONFIRMED, + OrderPayment.PAYMENT_STATE_REFUNDED, + OrderPayment.PAYMENT_STATE_PENDING, + OrderPayment.PAYMENT_STATE_CREATED, + ), + ) + .values("order") + .annotate(m=GroupConcat("provider", delimiter=",")) + .values("m") + .order_by() + ) + qs = ( + base_qs.annotate( + payment_providers=Subquery(p_providers, output_field=CharField()), + checked_in_lists=Subquery( + Checkin.objects.filter( + successful=True, + type=Checkin.TYPE_ENTRY, + position=OuterRef("pk"), + ) + .order_by() + .values("position") + .annotate( + c=GroupConcat( + "list__name", + # These appear not to work properly on SQLite. Well, we don't support SQLite outside testing + # anyways. + ordered="sqlite" + not in settings.DATABASES["default"]["ENGINE"], + distinct="sqlite" + not in settings.DATABASES["default"]["ENGINE"], + delimiter=", ", + ) + ) + .values("c") + ), + ) + .select_related( + "order", + "order__invoice_address", + "order__customer", + "item", + "variation", + "voucher", + "tax_rule", + "addon_to", + ) + .prefetch_related( + "subevent", + "subevent__meta_values", + "answers", + "answers__question", + "answers__options", + ) + ) + + has_subevents = self.events.filter(has_subevents=True).exists() + + # HEADERS START + # WICHTIG: + headers = [ + _("Product"), # wichtig + ] + questions = list(Question.objects.filter(event__in=self.events)) # für wichtig + options = defaultdict(list) # für wichtig + for q in questions: # wichtig + if q.type == Question.TYPE_CHOICE_MULTIPLE: + if form_data["group_multiple_choice"]: + for o in q.options.all(): + options[q.pk].append(o) + headers.append(str(q.question)) + else: + for o in q.options.all(): + headers.append(str(q.question) + " – " + str(o.answer)) + options[q.pk].append(o) + else: + if q.type == Question.TYPE_CHOICE: + for o in q.options.all(): + options[q.pk].append(o) + headers.append(str(q.question)) + + # MITTELWICHTIG: + headers += [ + _("Status"), # mittelwichtig + _("Email"), # mittelwichtig + ] + + # UNWICHTIG: + headers += [ + _("Order code"), # unwichtig + _("Order date"), # unwichtig + _("Order time"), # unwichtig + ] + if has_subevents: # unwichtig, unser Event hat das aber auch nicht + headers.append(pgettext("subevent", "Date")) + headers.append(_("Start date")) + headers.append(_("End date")) + headers += [ + _("Product ID"), # unwichtig + _("Attendee name"), # unwichtig + ] + name_scheme = ( # für unwichtig: Namensschema + PERSON_NAME_SCHEMES[self.event.settings.name_scheme] + if not self.is_multievent + else None + ) + if name_scheme and len(name_scheme["fields"]) > 1: # unwichtig: Namensschema + for k, label, w in name_scheme["fields"]: + headers.append(_("Attendee name") + ": " + str(label)) + headers += [ + _("Attendee email"), # unwichtig + _("Order comment"), # unwichtig + _("Payment providers"), # unwichtig + ] + + # get meta_data labels from first cached event + meta_data_labels = next(iter(self.event_object_cache.values())).meta_data.keys() + if has_subevents: # unwichtig + headers += meta_data_labels + + # SEHR UNWICHTIG: + headers += [ + _("Event slug"), # sehr unwichtig + _("Event name"), # sehr unwichtig + _("Position ID"), # sehr unwichtig + _("Phone number"), # sehr unwichtig + _("Variation"), # sehr unwichtig + _("Variation ID"), # sehr unwichtig + _("Price"), # sehr unwichtig + _("Tax rate"), # sehr unwichtig + _("Tax rule"), # sehr unwichtig + _("Tax value"), # sehr unwichtig + _("Company"), # sehr unwichtig + _("Address"), # sehr unwichtig + _("ZIP code"), # sehr unwichtig + _("City"), # sehr unwichtig + _("Country"), # sehr unwichtig + pgettext("address", "State"), # sehr unwichtig + _("Voucher"), # sehr unwichtig + _("Pseudonymization ID"), # sehr unwichtig + _("Ticket secret"), # sehr unwichtig + _("Seat ID"), # sehr unwichtig + _("Seat name"), # sehr unwichtig + _("Seat zone"), # sehr unwichtig + _("Seat row"), # sehr unwichtig + _("Seat number"), # sehr unwichtig + _("Blocked"), # sehr unwichtig + _("Valid from"), # sehr unwichtig + _("Valid until"), # sehr unwichtig + _("Follow-up date"), # sehr unwichtig + _("Add-on to position ID"), # sehr unwichtig + _("Company"), # sehr unwichtig + _("Invoice address name"), # sehr unwichtig + ] + if name_scheme and len(name_scheme["fields"]) > 1: # sehr unwichtig + for k, label, w in name_scheme["fields"]: + headers.append(_("Invoice address name") + ": " + str(label)) + headers += [ + _("Invoice address street"), # sehr unwichtig + _("Invoice address ZIP code"), # sehr unwichtig + _("Invoice address city"), # sehr unwichtig + _("Invoice address country"), # sehr unwichtig + pgettext("address", "Invoice address state"), # sehr unwichtig + _("VAT ID"), # sehr unwichtig + _("Sales channel"), # sehr unwichtig + _("Order locale"), # sehr unwichtig + _("Email address verified"), # sehr unwichtig + _("External customer ID"), # sehr unwichtig + _("Check-in lists"), # sehr unwichtig + ] + + # UNSORTIERT: + yield headers + # HEADERS END + + all_ids = list( + base_qs.order_by("order__datetime", "positionid").values_list( + "pk", flat=True + ) + ) + yield self.ProgressSetTotal(total=len(all_ids)) + for ids in chunked_iterable(all_ids, 1000): + ops = sorted(qs.filter(id__in=ids), key=lambda k: ids.index(k.pk)) + + for op in ops: + order = op.order + tz = ZoneInfo(self.event_object_cache[order.event_id].settings.timezone) + # ROWS START + # WICHTIG: + row = [ + str(op.item), # wichtig_("Product") + ] + # Eigene Fragen Start + acache = {} # für wichtig (Eigene Fragen) + for a in op.answers.all(): # für wichtig (Eigene Fragen) + # We do not want to localize Date, Time and Datetime question answers, as those can lead + # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). + if a.question.type in ( + Question.TYPE_CHOICE_MULTIPLE, + Question.TYPE_CHOICE, + ): + acache[a.question_id] = set(o.pk for o in a.options.all()) + elif a.question.type in Question.UNLOCALIZED_TYPES: + acache[a.question_id] = a.answer + else: + acache[a.question_id] = str(a) + for q in questions: # wichtig (Eigene Fragen) + if q.type == Question.TYPE_CHOICE_MULTIPLE: + if form_data["group_multiple_choice"]: + row.append( + ", ".join( + str(o.answer) + for o in options[q.pk] + if o.pk in acache.get(q.pk, set()) + ) + ) + else: + for o in options[q.pk]: + row.append( + _("Yes") + if o.pk in acache.get(q.pk, set()) + else _("No") + ) + elif q.type == Question.TYPE_CHOICE: + # Join is only necessary if the question type was modified but also keeps the code simpler here + # as we'd otherwise need some [0] and existance checks + row.append( + ", ".join( + str(o.answer) + for o in options[q.pk] + if o.pk in acache.get(q.pk, set()) + ) + ) + else: + row.append(acache.get(q.pk, "")) + # Eigene Fragen End + + # MITTELWICHTIG: + row += [ + ( # mittelwichtig _("Status") + _("canceled") + if op.canceled + else order.get_extended_status_display() + ), + order.email, # mittelwichtig_("Email" + ] + + # UNWICHTIG: + row += [ + order.code, # unwichtig_("Order code") + order.datetime.astimezone(tz).strftime( + "%Y-%m-%d" + ), # unwichtig _("Order date") + order.datetime.astimezone(tz).strftime( + "%H:%M:%S" + ), # unwichtig _("Order time") + ] + if has_subevents: # unwichtig , unser Event hat das aber auch nicht + if op.subevent: + row.append(op.subevent.name) + row.append( + op.subevent.date_from.astimezone( + self.event_object_cache[order.event_id].timezone + ).strftime("%Y-%m-%d %H:%M:%S") + ) + if op.subevent.date_to: + row.append( + op.subevent.date_to.astimezone( + self.event_object_cache[order.event_id].timezone + ).strftime("%Y-%m-%d %H:%M:%S") + ) + else: + row.append("") + else: + row.append("") + row.append("") + row.append("") + row += [ + str(op.item_id), # unwichtig _("Product ID") + op.attendee_name, # unwichtig _("Attendee name") + ] + if name_scheme and len(name_scheme["fields"]) > 1: # für unwichtig + for k, label, w in name_scheme["fields"]: + row.append(get_name_parts_localized(op.attendee_name_parts, k)) + row += [ + op.attendee_email, # unwichtig _("Attendee email") + ] + row.append(order.comment) # unwichtig_("Order comment") + row.append( # unwichtig_("Payment providers") + ", ".join( + [ + str(self.providers.get(p, p)) + for p in sorted( + set((op.payment_providers or "").split(",")) + ) + if p and p != "free" + ] + ) + ) + + if has_subevents: # unwichtig + if op.subevent: + row += op.subevent.meta_data.values() + else: + row += [""] * len(meta_data_labels) + + # SEHR UNWICHTIG: + row += [ + self.event_object_cache[ # sehr unwichtig_("Event slug") + order.event_id + ].slug, + str( # sehr unwichtig_("Event name") + self.event_object_cache[order.event_id].name + ), + op.positionid, # sehr unwichtig_("Position ID") + ( + str(order.phone) if order.phone else "" + ), # sehr unwichtig_("Phone number") + ( + str(op.variation) if op.variation else "" + ), # sehr unwichtig_("Variation") + ( + str(op.variation_id) if op.variation_id else "" + ), # sehr unwichtig_("Variation ID") + op.price, # sehr unwichtig_("Price") + op.tax_rate, # sehr unwichtig_("Tax rate") + ( + str(op.tax_rule) if op.tax_rule else "" + ), # sehr unwichtig_("Tax rule") + op.tax_value, # sehr unwichtig_("Tax value") + op.company or "", # sehr unwichtig_("Company") + op.street or "", # sehr unwichtig_("Address") + op.zipcode or "", # sehr unwichtig_("ZIP code") + op.city or "", # sehr unwichtig_("City") + op.country if op.country else "", # sehr unwichtig_("Country") + op.state or "", # sehr unwichtig("address", "State") + op.voucher.code if op.voucher else "", # sehr unwichtig_("Voucher") + op.pseudonymization_id, # sehr unwichtig_("Pseudonymization ID") + op.secret, # sehr unwichtig_("Ticket secret") + ] + if op.seat: # sehr unwichtig + row += [ + op.seat.seat_guid, # sehr unwichtig_("Seat ID") + str(op.seat), # sehr unwichtig_("Seat name") + op.seat.zone_name, # sehr unwichtig_("Seat zone") + op.seat.row_name, # sehr unwichtig_("Seat row") + op.seat.seat_number, # sehr unwichtig_("Seat number") + ] + else: + row += ["", "", "", "", ""] # sehr unwichtig + row += [ # sehr unwichtig + _("Yes") if op.blocked else "", # sehr unwichtig_("Blocked") + ( # sehr unwichtig_("Valid from" + date_format( + op.valid_from.astimezone(tz), "SHORT_DATETIME_FORMAT" + ) + if op.valid_from + else "" + ), + ( # sehr unwichtig_("Valid until") + date_format( + op.valid_until.astimezone(tz), "SHORT_DATETIME_FORMAT" + ) + if op.valid_until + else "" + ), + ] + row.append( # sehr unwichtig("Follow-up date") + order.custom_followup_at.strftime("%Y-%m-%d") + if order.custom_followup_at + else "" + ) + row.append( + op.addon_to.positionid if op.addon_to_id else "" + ) # sehr unwichtig_("Add-on to position ID") + try: # sehr unwichtig + row += [ + order.invoice_address.company, # sehr unwichtig_("Company") + order.invoice_address.name, # sehr unwichtig_("Invoice address name") + ] + if ( + name_scheme and len(name_scheme["fields"]) > 1 + ): # sehr unwichtig_("Invoice address name: {fields}") + for k, label, w in name_scheme["fields"]: + row.append( + get_name_parts_localized( + order.invoice_address.name_parts, k + ) + ) + row += [ + order.invoice_address.street, # sehr unwichtig_("Invoice address street") + order.invoice_address.zipcode, # sehr unwichtig_("Invoice address ZIP code") + order.invoice_address.city, # sehr unwichtig_("Invoice address city") + ( # sehr unwichtig_("Invoice address country") + order.invoice_address.country + if order.invoice_address.country + else order.invoice_address.country_old + ), + order.invoice_address.state, # sehr unwichtig("address", "Invoice address state") + order.invoice_address.vat_id, # sehr unwichtig_("VAT ID") + ] + except InvoiceAddress.DoesNotExist: + row += [""] * ( + 8 + + ( + len(name_scheme["fields"]) + if name_scheme and len(name_scheme["fields"]) > 1 + else 0 + ) + ) + row += [ # sehr unwichtig + order.sales_channel, # sehr unwichtig_("Sales channel") + order.locale, # sehr unwichtig_("Order locale") + ( + _("Yes") if order.email_known_to_work else _("No") + ), # sehr unwichtig_("Email address verified") + ( # sehr unwichtig_("External customer ID") + str(order.customer.external_identifier) + if order.customer and order.customer.external_identifier + else "" + ), + ] + row.append( + op.checked_in_lists or "" + ) # sehr unwichtig_("Check-in lists") + + # UNSORTIERT: + + yield row + # ROWS END + + def get_filename(self): + if self.is_multievent: + return "{}_orders".format(self.organizer.slug) + else: + return "{}_orders".format(self.event.slug) + + +@receiver(register_data_exporters, dispatch_uid="exporter_relevant_orderlist") +def register_relevant_orderlist_exporter(sender, **kwargs): + return RelevantOrderListExporter + + +@receiver( + register_multievent_data_exporters, dispatch_uid="multiexporter_relevant_orderlist" +) +def register_multievent_relevant_orderlist_exporter(sender, **kwargs): + return RelevantOrderListExporter diff --git a/src/pretix/locale/de/LC_MESSAGES/django.po b/src/pretix/locale/de/LC_MESSAGES/django.po index eb09c41b8..f394f3970 100644 --- a/src/pretix/locale/de/LC_MESSAGES/django.po +++ b/src/pretix/locale/de/LC_MESSAGES/django.po @@ -1821,6 +1821,10 @@ msgstr "Ohne gültige Mitgliedschaft verstecken" msgid "Order data" msgstr "Bestelldaten" +#: pretix/base/exporters/relevant_orderlist.py:86 +msgid "Order data (sorted by relevance)" +msgstr "Bestelldaten (nach Relevanz sortiert)" + #: pretix/base/exporters/json.py:53 msgid "" "Download a structured JSON representation of all orders. This might be " @@ -1857,6 +1861,18 @@ msgstr "" "Bestellposition und das dritte eine Zeile für jede zusätzlich erhobene " "Gebühr." +#: pretix/base/exporters/relevant_orderlist.py:88 +msgid "" +"Download a spreadsheet of all orders. The spreadsheet will include three " +"sheets, one with a line for every order, one with a line for every order " +"position, and one with a line for every additional fee charged in an " +"order. The most relevant data is in the first columns of the tables." +msgstr "" +"Tabelle (Excel oder CSV) mit allen Bestellungen. Das erste Tabellenblatt " +"enthält eine Zeile für jede Bestellung, das zweite eine Zeile für jede " +"Bestellposition und das dritte eine Zeile für jede zusätzlich erhobene " +"Gebühr. Die relevantesten Daten sind in den ersten Spalten der Tabellen." + #: pretix/base/exporters/orderlist.py:100 pretix/base/models/orders.py:332 #: pretix/control/navigation.py:255 pretix/control/navigation.py:362 #: pretix/control/templates/pretixcontrol/orders/index.html:8 From c85b4961872642bb01d85e2e72ca5478ace73a25 Mon Sep 17 00:00:00 2001 From: luelista Date: Fri, 22 Aug 2025 09:31:01 +0200 Subject: [PATCH 07/10] Organizer plugins: Do not show plugins as active if they are inactive on org-level (#5396) --- .../pretixcontrol/organizers/plugins.html | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/pretix/control/templates/pretixcontrol/organizers/plugins.html b/src/pretix/control/templates/pretixcontrol/organizers/plugins.html index 964132f3a..de4ec952d 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/plugins.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/plugins.html @@ -69,34 +69,36 @@ {% if show_meta %} {{ plugin.version }} {% endif %} - {% if is_active and level == "organizer" %} - - - {% trans "Active" %} - - {% elif events_counter == events_total %} - - - {% trans "Active (all events)" %} - - {% elif events_counter %} - - - {% blocktrans trimmed count count=events_counter %} - Active ({{ count }} event) - {% plural %} - Active ({{ count }} events) - {% endblocktrans %} - - {% elif level == "event_organizer" %} - - - {% blocktrans trimmed count count=0 %} - Active ({{ count }} event) - {% plural %} - Active ({{ count }} events) - {% endblocktrans %} - + {% if is_active or plugin.level == "event" %} + {% if plugin.level == "organizer" %} + + + {% trans "Active" %} + + {% elif events_total and events_counter == events_total %} + + + {% trans "Active (all events)" %} + + {% elif events_counter %} + + + {% blocktrans trimmed count count=events_counter %} + Active ({{ count }} event) + {% plural %} + Active ({{ count }} events) + {% endblocktrans %} + + {% elif level == "event_organizer" %} + + + {% blocktrans trimmed count count=0 %} + Active ({{ count }} event) + {% plural %} + Active ({{ count }} events) + {% endblocktrans %} + + {% endif %} {% endif %} {% include "pretixcontrol/event/fragment_plugin_description.html" with plugin=plugin %} From e4b8c5da251d62e6d1d5e1d6a7b17c317c168b47 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Sat, 23 Aug 2025 09:07:33 +0200 Subject: [PATCH 08/10] Bump hierarkey to 2.0.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 43cd6059e..9c689167d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ dependencies = [ "django-filter==25.1", "django-formset-js-improved==0.5.0.3", "django-formtools==2.5.1", - "django-hierarkey==2.0.*", + "django-hierarkey==2.0.*,>=2.0.1", "django-hijack==3.7.*", "django-i18nfield==1.10.*", "django-libsass==0.9", From 2d42c1f16603d0c834465bb09f7d0e578016a30e Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Sat, 23 Aug 2025 10:15:29 +0200 Subject: [PATCH 09/10] Bump to 2025.7.1 --- src/pretix/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pretix/__init__.py b/src/pretix/__init__.py index 4f235f33d..400002680 100644 --- a/src/pretix/__init__.py +++ b/src/pretix/__init__.py @@ -19,4 +19,4 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -__version__ = "2025.7.0" +__version__ = "2025.7.1" From 64b56afe44cfe2aaf5057e01cb437c4ebe6d2686 Mon Sep 17 00:00:00 2001 From: Philipp Kern Date: Tue, 16 Sep 2025 19:00:58 +0200 Subject: [PATCH 10/10] Fix language file bug --- src/pretix/locale/de/LC_MESSAGES/django.po | 58 ++++--------------- .../locale/de_Informal/LC_MESSAGES/django.po | 58 ++++--------------- 2 files changed, 20 insertions(+), 96 deletions(-) diff --git a/src/pretix/locale/de/LC_MESSAGES/django.po b/src/pretix/locale/de/LC_MESSAGES/django.po index 5d7e8b076..78f144f97 100644 --- a/src/pretix/locale/de/LC_MESSAGES/django.po +++ b/src/pretix/locale/de/LC_MESSAGES/django.po @@ -831,7 +831,7 @@ msgstr "Details der Bestellposition" #: pretix/base/datasync/sourcefields.py:129 msgid "Attendee details" -msgstr "Details Teilnehmer*in" +msgstr "Details Teilnehmer" #: pretix/base/datasync/sourcefields.py:130 pretix/base/exporters/answers.py:66 #: pretix/base/models/items.py:1767 pretix/control/navigation.py:172 @@ -893,13 +893,13 @@ msgstr "Veranstaltungs- oder Termininformationen" #: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 #: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:36 msgid "Attendee name" -msgstr "Name Teilnehmer*in" +msgstr "Name Teilnehmer" #: pretix/base/datasync/sourcefields.py:187 #: pretix/base/datasync/sourcefields.py:604 #: pretix/base/datasync/sourcefields.py:628 msgid "Attendee" -msgstr "Teilnehmer*in" +msgstr "Teilnehmer" #: pretix/base/datasync/sourcefields.py:207 #: pretix/base/exporters/orderlist.py:611 pretix/base/forms/questions.py:685 @@ -910,11 +910,11 @@ msgstr "Teilnehmer*in" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:172 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:175 msgid "Attendee email" -msgstr "E-Mail Teilnehmer*in" +msgstr "E-Mail Teilnehmer" #: pretix/base/datasync/sourcefields.py:219 msgid "Attendee or order email" -msgstr "E-Mail Teilnehmer*in oder Bestellung" +msgstr "E-Mail Teilnehmer oder Bestellung" #: pretix/base/datasync/sourcefields.py:232 pretix/base/pdf.py:186 #: pretix/control/templates/pretixcontrol/order/index.html:595 @@ -923,23 +923,23 @@ msgstr "E-Mail Teilnehmer*in oder Bestellung" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:182 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:185 msgid "Attendee company" -msgstr "Teilnehmer*innen-Firma" +msgstr "Teilnehmer-Firma" #: pretix/base/datasync/sourcefields.py:241 msgid "Attendee address street" -msgstr "Teilnehmer*innen-Adresse: Straße" +msgstr "Teilnehmer-Adresse: Straße" #: pretix/base/datasync/sourcefields.py:250 msgid "Attendee address ZIP code" -msgstr "Teilnehmer*innen-Adresse: PLZ" +msgstr "Teilnehmer-Adresse: PLZ" #: pretix/base/datasync/sourcefields.py:259 msgid "Attendee address city" -msgstr "Teilnehmer*innen-Adresse: Stadt" +msgstr "Teilnehmer-Adresse: Stadt" #: pretix/base/datasync/sourcefields.py:268 msgid "Attendee address country" -msgstr "Teilnehmer*innen-Adresse: Land" +msgstr "Teilnehmer-Adresse: Land" #: pretix/base/datasync/sourcefields.py:279 pretix/base/pdf.py:344 msgid "Invoice address company" @@ -2523,35 +2523,6 @@ msgstr "Ende" msgid "Product" msgstr "Produkt" -#: pretix/base/exporters/orderlist.py:595 -#: pretix/base/exporters/orderlist.py:600 pretix/base/forms/questions.py:679 -#: pretix/base/modelimport_orders.py:313 pretix/base/models/customers.py:300 -#: pretix/base/models/orders.py:1504 pretix/base/pdf.py:172 -#: pretix/control/forms/filter.py:648 pretix/control/forms/organizer.py:986 -#: pretix/control/templates/pretixcontrol/order/index.html:514 -#: pretix/control/templates/pretixcontrol/organizers/customer.html:120 -#: pretix/control/views/item.py:442 pretix/plugins/badges/exporters.py:495 -#: pretix/plugins/checkinlists/exporters.py:120 -#: pretix/plugins/checkinlists/exporters.py:493 -#: pretix/plugins/ticketoutputpdf/exporters.py:94 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:162 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:165 -#: pretix/presale/templates/pretixpresale/event/fragment_change_form.html:38 -#: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 -#: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:36 -msgid "Attendee name" -msgstr "Name Teilnehmer" - -#: pretix/base/exporters/orderlist.py:602 pretix/base/forms/questions.py:685 -#: pretix/base/models/customers.py:307 pretix/base/models/orders.py:1512 -#: pretix/base/pdf.py:214 -#: pretix/control/templates/pretixcontrol/order/index.html:519 -#: pretix/control/views/item.py:454 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:172 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:175 -msgid "Attendee email" -msgstr "E-Mail Teilnehmer" - #: pretix/base/exporters/orderlist.py:609 pretix/base/models/vouchers.py:312 #: pretix/control/templates/pretixcontrol/vouchers/bulk.html:5 #: pretix/control/templates/pretixcontrol/vouchers/detail.html:6 @@ -7901,15 +7872,6 @@ msgstr "Preis inklusive enthaltener und Zusatzprodukte" msgid "John Doe" msgstr "Max Mustermann" -#: pretix/base/pdf.py:177 -#: pretix/control/templates/pretixcontrol/order/index.html:543 -#: pretix/plugins/badges/exporters.py:496 -#: pretix/plugins/ticketoutputpdf/exporters.py:95 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:182 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:185 -msgid "Attendee company" -msgstr "Teilnehmer-Firma" - #: pretix/base/pdf.py:178 pretix/base/pdf.py:336 #: pretix/base/services/tickets.py:119 pretix/control/views/pdf.py:110 #: pretix/control/views/pdf.py:116 pretix/control/views/pdf.py:123 diff --git a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po index b08c990a1..fe88cd749 100644 --- a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po +++ b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po @@ -832,7 +832,7 @@ msgstr "Details der Bestellposition" #: pretix/base/datasync/sourcefields.py:129 msgid "Attendee details" -msgstr "Details Teilnehmer*in" +msgstr "Details Teilnehmer" #: pretix/base/datasync/sourcefields.py:130 pretix/base/exporters/answers.py:66 #: pretix/base/models/items.py:1767 pretix/control/navigation.py:172 @@ -894,13 +894,13 @@ msgstr "Veranstaltungs- oder Termininformationen" #: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 #: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:36 msgid "Attendee name" -msgstr "Name Teilnehmer*in" +msgstr "Name Teilnehmer" #: pretix/base/datasync/sourcefields.py:187 #: pretix/base/datasync/sourcefields.py:604 #: pretix/base/datasync/sourcefields.py:628 msgid "Attendee" -msgstr "Teilnehmer*in" +msgstr "Teilnehmer" #: pretix/base/datasync/sourcefields.py:207 #: pretix/base/exporters/orderlist.py:611 pretix/base/forms/questions.py:685 @@ -911,11 +911,11 @@ msgstr "Teilnehmer*in" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:172 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:175 msgid "Attendee email" -msgstr "E-Mail Teilnehmer*in" +msgstr "E-Mail Teilnehmer" #: pretix/base/datasync/sourcefields.py:219 msgid "Attendee or order email" -msgstr "E-Mail Teilnehmer*in oder Bestellung" +msgstr "E-Mail Teilnehmer oder Bestellung" #: pretix/base/datasync/sourcefields.py:232 pretix/base/pdf.py:186 #: pretix/control/templates/pretixcontrol/order/index.html:595 @@ -924,23 +924,23 @@ msgstr "E-Mail Teilnehmer*in oder Bestellung" #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:182 #: pretix/presale/templates/pretixpresale/event/fragment_cart.html:185 msgid "Attendee company" -msgstr "Teilnehmer*innen-Firma" +msgstr "Teilnehmer-Firma" #: pretix/base/datasync/sourcefields.py:241 msgid "Attendee address street" -msgstr "Teilnehmer*innen-Adresse: Straße" +msgstr "Teilnehmer-Adresse: Straße" #: pretix/base/datasync/sourcefields.py:250 msgid "Attendee address ZIP code" -msgstr "Teilnehmer*innen-Adresse: PLZ" +msgstr "Teilnehmer-Adresse: PLZ" #: pretix/base/datasync/sourcefields.py:259 msgid "Attendee address city" -msgstr "Teilnehmer*innen-Adresse: Stadt" +msgstr "Teilnehmer-Adresse: Stadt" #: pretix/base/datasync/sourcefields.py:268 msgid "Attendee address country" -msgstr "Teilnehmer*innen-Adresse: Land" +msgstr "Teilnehmer-Adresse: Land" #: pretix/base/datasync/sourcefields.py:279 pretix/base/pdf.py:344 msgid "Invoice address company" @@ -2508,35 +2508,6 @@ msgstr "Ende" msgid "Product" msgstr "Produkt" -#: pretix/base/exporters/orderlist.py:595 -#: pretix/base/exporters/orderlist.py:600 pretix/base/forms/questions.py:679 -#: pretix/base/modelimport_orders.py:313 pretix/base/models/customers.py:300 -#: pretix/base/models/orders.py:1504 pretix/base/pdf.py:172 -#: pretix/control/forms/filter.py:648 pretix/control/forms/organizer.py:986 -#: pretix/control/templates/pretixcontrol/order/index.html:514 -#: pretix/control/templates/pretixcontrol/organizers/customer.html:120 -#: pretix/control/views/item.py:442 pretix/plugins/badges/exporters.py:495 -#: pretix/plugins/checkinlists/exporters.py:120 -#: pretix/plugins/checkinlists/exporters.py:493 -#: pretix/plugins/ticketoutputpdf/exporters.py:94 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:162 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:165 -#: pretix/presale/templates/pretixpresale/event/fragment_change_form.html:38 -#: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:50 -#: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:36 -msgid "Attendee name" -msgstr "Name Teilnehmer" - -#: pretix/base/exporters/orderlist.py:602 pretix/base/forms/questions.py:685 -#: pretix/base/models/customers.py:307 pretix/base/models/orders.py:1512 -#: pretix/base/pdf.py:214 -#: pretix/control/templates/pretixcontrol/order/index.html:519 -#: pretix/control/views/item.py:454 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:172 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:175 -msgid "Attendee email" -msgstr "E-Mail Teilnehmer" - #: pretix/base/exporters/orderlist.py:609 pretix/base/models/vouchers.py:312 #: pretix/control/templates/pretixcontrol/vouchers/bulk.html:5 #: pretix/control/templates/pretixcontrol/vouchers/detail.html:6 @@ -7877,15 +7848,6 @@ msgstr "Preis inklusive enthaltener und Zusatzprodukte" msgid "John Doe" msgstr "Max Mustermann" -#: pretix/base/pdf.py:177 -#: pretix/control/templates/pretixcontrol/order/index.html:543 -#: pretix/plugins/badges/exporters.py:496 -#: pretix/plugins/ticketoutputpdf/exporters.py:95 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:182 -#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:185 -msgid "Attendee company" -msgstr "Teilnehmer-Firma" - #: pretix/base/pdf.py:178 pretix/base/pdf.py:336 #: pretix/base/services/tickets.py:119 pretix/control/views/pdf.py:110 #: pretix/control/views/pdf.py:116 pretix/control/views/pdf.py:123