forked from CGM_Public/pretix_original
Compare commits
58
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fd683b5c8 | ||
|
|
c16491889b | ||
|
|
1eb1d8df5f | ||
|
|
3f47cf785c | ||
|
|
e8859cb2e2 | ||
|
|
61ab6f729d | ||
|
|
79c9ba3cf3 | ||
|
|
1d86f7a0c3 | ||
|
|
e259b3994a | ||
|
|
18e97624fd | ||
|
|
1c9a245231 | ||
|
|
b51ca58820 | ||
|
|
7a48cac862 | ||
|
|
1bdcc4580e | ||
|
|
dd10bdd433 | ||
|
|
f7a74c2e74 | ||
|
|
4037e1886d | ||
|
|
c4ae363fdb | ||
|
|
3df64a46e7 | ||
|
|
69502986ad | ||
|
|
51ea63335c | ||
|
|
dc76b554f8 | ||
|
|
f8be8296dd | ||
|
|
b3c917925c | ||
|
|
4954373a04 | ||
|
|
5571ec3858 | ||
|
|
9ef3139905 | ||
|
|
3139b9fe6f | ||
|
|
437d33ba79 | ||
|
|
0a9890b1b0 | ||
|
|
1420ad43db | ||
|
|
30da7a6429 | ||
|
|
a2f3dcce02 | ||
|
|
41f5ca3f9d | ||
|
|
817f1e0371 | ||
|
|
35fc001768 | ||
|
|
002416e435 | ||
|
|
4917249bab | ||
|
|
afd2468375 | ||
|
|
54d06dd7f8 | ||
|
|
5e59844cf5 | ||
|
|
0d2a981674 | ||
|
|
943aeaa31f | ||
|
|
cfe0f67f0d | ||
|
|
635bb94cc4 | ||
|
|
cf732ce173 | ||
|
|
74e9a4ad2d | ||
|
|
570357e9be | ||
|
|
473375d4ae | ||
|
|
a78b698520 | ||
|
|
332c968294 | ||
|
|
ad12c344c5 | ||
|
|
91c0db1ac0 | ||
|
|
4d231b70aa | ||
|
|
ab2f6f6bed | ||
|
|
28458f7b85 | ||
|
|
50ff968c17 | ||
|
|
0b4064f14f |
@@ -26,7 +26,7 @@ installation guides):
|
||||
* `Docker`_
|
||||
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
|
||||
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
|
||||
* A `PostgreSQL`_ 9.6+ database server
|
||||
* A `PostgreSQL`_ 11+ database server
|
||||
* A `redis`_ server
|
||||
|
||||
We also recommend that you use a firewall, although this is not a pretix-specific recommendation. If you're new to
|
||||
@@ -321,11 +321,11 @@ workers, e.g. ``docker run … taskworker -Q notifications --concurrency 32``.
|
||||
|
||||
|
||||
.. _Docker: https://docs.docker.com/engine/installation/linux/debian/
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
|
||||
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
|
||||
.. _Let's Encrypt: https://letsencrypt.org/
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _redis website: https://redis.io/topics/security
|
||||
|
||||
@@ -21,6 +21,7 @@ Requirements
|
||||
Please set up the following systems beforehand, we'll not explain them here in detail (but see these links for external
|
||||
installation guides):
|
||||
|
||||
* A python 3.9+ installation
|
||||
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
|
||||
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
|
||||
* A `PostgreSQL`_ 11+ database server
|
||||
@@ -323,11 +324,11 @@ Then, proceed like after any plugin installation::
|
||||
(venv)$ python -m pretix updatestyles
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
|
||||
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
|
||||
.. _Let's Encrypt: https://letsencrypt.org/
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
|
||||
@@ -70,6 +70,11 @@ Endpoints
|
||||
|
||||
The ``public_url`` field has been added.
|
||||
|
||||
.. versionchanged:: 5.0
|
||||
|
||||
The ``date_from_before``, ``date_from_after``, ``date_to_before``, and ``date_to_after`` query parameters have been
|
||||
added.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/
|
||||
|
||||
Returns a list of all events within a given organizer the authenticated user/token has access to.
|
||||
@@ -141,6 +146,10 @@ Endpoints
|
||||
:query has_subevents: If set to ``true``/``false``, only events with a matching value of ``has_subevents`` are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned. Event series are never (always) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned. Event series are never (always) returned.
|
||||
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
|
||||
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
|
||||
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
|
||||
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned. Event series are never returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date_from`` and
|
||||
``slug``. Keep in mind that ``date_from`` of event series does not really tell you anything.
|
||||
|
||||
@@ -111,7 +111,7 @@ Listing available exporters
|
||||
"input_parameters": [
|
||||
{
|
||||
"name": "events",
|
||||
"required": true
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "_format",
|
||||
|
||||
@@ -19,6 +19,7 @@ Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the medium
|
||||
type string Type of medium, e.g. ``"barcode"`` or ``"nfc_uid"``.
|
||||
organizer string Organizer slug of the organizer who "owns" this medium.
|
||||
identifier string Unique identifier of the medium. The format depends on the ``type``.
|
||||
active boolean Whether this medium may be used.
|
||||
created datetime Date of creation
|
||||
@@ -67,6 +68,7 @@ Endpoints
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"organizer": "bigevents",
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
@@ -123,6 +125,7 @@ Endpoints
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"organizer": "bigevents",
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
@@ -152,6 +155,9 @@ Endpoints
|
||||
Look up a new reusable medium by its identifier. In some cases, this might lead to the automatic creation of a new
|
||||
medium behind the scenes.
|
||||
|
||||
This endpoint, and this endpoint only, might return media from a different organizer if there is a cross-acceptance
|
||||
agreement. In this case, only linked gift cards will be returned, no order position or customer records,
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
@@ -176,6 +182,7 @@ Endpoints
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"organizer": "bigevents",
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
@@ -235,6 +242,7 @@ Endpoints
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"organizer": "bigevents",
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
@@ -291,6 +299,7 @@ Endpoints
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"organizer": "bigevents",
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
|
||||
@@ -63,6 +63,11 @@ last_modified datetime Last modificati
|
||||
|
||||
The ``search`` query parameter has been added to filter sub-events by their name or location in any language.
|
||||
|
||||
.. versionchanged:: 5.0
|
||||
|
||||
The ``date_from_before``, ``date_from_after``, ``date_to_before``, and ``date_to_after`` query parameters have been
|
||||
added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -130,6 +135,10 @@ Endpoints
|
||||
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
|
||||
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
|
||||
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
|
||||
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
|
||||
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||
:query search: Only return events matching a given search query.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
@@ -458,6 +467,10 @@ Endpoints
|
||||
:query event__live: If set to ``true``/``false``, only events with a matching value of ``live`` on the parent event are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
|
||||
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
|
||||
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
|
||||
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
|
||||
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||
:query sales_channel: If set to a sales channel identifier, the response will only contain subevents from events available on this sales channel.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
|
||||
@@ -20,11 +20,16 @@ internal_name string An optional nam
|
||||
rate decimal (string) Tax rate in percent
|
||||
price_includes_tax boolean If ``true`` (default), tax is assumed to be included in
|
||||
the specified product price
|
||||
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied
|
||||
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied. Will
|
||||
be ignored if custom rules are set.
|
||||
home_country string Merchant country (required for reverse charge), can be
|
||||
``null`` or empty string
|
||||
keep_gross_if_rate_changes boolean If ``true``, changes of the tax rate based on custom
|
||||
rules keep the gross price constant (default is ``false``)
|
||||
custom_rules object Dynamic rules specification. Each list element
|
||||
corresponds to one rule that will be processed in order.
|
||||
The current version of the schema in use can be found
|
||||
`here`_.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -32,6 +37,10 @@ keep_gross_if_rate_changes boolean If ``true``, ch
|
||||
|
||||
The ``internal_name`` and ``keep_gross_if_rate_changes`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 2023.6
|
||||
|
||||
The ``custom_rules`` attribute has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -68,6 +77,7 @@ Endpoints
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"keep_gross_if_rate_changes": false,
|
||||
"custom_rules": null,
|
||||
"home_country": "DE"
|
||||
}
|
||||
]
|
||||
@@ -108,6 +118,7 @@ Endpoints
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"keep_gross_if_rate_changes": false,
|
||||
"custom_rules": null,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
@@ -156,6 +167,7 @@ Endpoints
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"keep_gross_if_rate_changes": false,
|
||||
"custom_rules": null,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
@@ -203,6 +215,7 @@ Endpoints
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"keep_gross_if_rate_changes": false,
|
||||
"custom_rules": null,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
@@ -242,3 +255,5 @@ Endpoints
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this tax rule cannot be deleted since it is currently in use.
|
||||
|
||||
.. _here: https://github.com/pretix/pretix/blob/master/src/pretix/static/schema/tax-rules-custom.schema.json
|
||||
|
||||
@@ -50,6 +50,10 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.order.payment.confirmed``
|
||||
* ``pretix.event.order.approved``
|
||||
* ``pretix.event.order.denied``
|
||||
* ``pretix.event.orders.waitinglist.added``
|
||||
* ``pretix.event.orders.waitinglist.changed``
|
||||
* ``pretix.event.orders.waitinglist.deleted``
|
||||
* ``pretix.event.orders.waitinglist.voucher_assigned``
|
||||
* ``pretix.event.checkin``
|
||||
* ``pretix.event.checkin.reverted``
|
||||
* ``pretix.event.added``
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
ePayBL
|
||||
======
|
||||
|
||||
.. note::
|
||||
|
||||
Since ePayBL is only available to german federal, provincial and communal entities, the following page is also
|
||||
only provided in german. Should you require assistance with ePayBL and do not speak this language, please feel free
|
||||
reach out to support@pretix.eu.
|
||||
|
||||
|
||||
Einführung
|
||||
----------
|
||||
|
||||
.. note::
|
||||
|
||||
Sollten Sie lediglich schnell entscheiden wollen, welcher Kontierungsmodus in den Einstellungen des pretix
|
||||
ePayBL-plugins gewählt werden soll, so springen Sie direkt zur Sektion :ref:`Kontierungsmodus`.
|
||||
|
||||
|
||||
`ePayBL`_ - das ePayment-System von Bund und Länder - ist das am weitesten verbreitete Zahlungssystem für Bundes-, Länder-
|
||||
sowie kommunale Aufgabenträger. Während es nur wie eines von vielen anderen Zahlungssystemen scheint, so bietet es
|
||||
seinen Nutzern besondere Vorteile, wie die automatische Erfassung von Zahlungsbelegen, dem Übertragen von Buchungen in
|
||||
Haushaltskassen/-systeme sowie die automatische Erfassung von Kontierungen und Steuermerkmalen.
|
||||
|
||||
Rein technisch gesehen ist ePayBL hierbei nicht ein eigenständiger Zahlungsdienstleister sondern nur ein eine Komponente
|
||||
im komplexen System, dass die Zahlungsabwicklung für Kommunen und Behörden ist.
|
||||
|
||||
Im folgenden der schematische Aufbau einer Umgebung, in welcher ePayBL zum Einsatz kommt:
|
||||
|
||||
.. figure:: img/epaybl_flowchart.png
|
||||
:class: screenshot
|
||||
|
||||
Quelle: Integrationshandbuch ePayBL-Konnektor, DResearch Digital Media Systems GmbH
|
||||
|
||||
|
||||
In diesem Schaubild stellt pretix, bzw. die von Ihnen als Veranstalter angelegten Ticketshops, das Fachverfahren dar.
|
||||
|
||||
ePayBL stellt das Bindeglied zwischen den Fachverfahren, Haushaltssystemen und dem eigentlichen Zahlungsdienstleister,
|
||||
dem sog. ZV-Provider dar. Dieser ZV-Provider ist die Stelle, welche die eigentlichen Kundengelder einzieht und an den
|
||||
Händler auszahlt. Das Gros der Zahlungsdienstleister unterstützt pretix hierbei auch direkt; sprich: Sollten Sie die
|
||||
Anbindung an Ihre Haushaltssysteme nicht benötigen, kann eine direkte Anbindung in der Regel ebenso - und dies bei meist
|
||||
vermindertem Aufwand - vorgenommen werden.
|
||||
|
||||
In der Vergangenheit zeigte sich jedoch schnell, dass nicht jeder IT-Dienstleister immer sofort die neueste Version von
|
||||
ePayBL seinen Nutzern angeboten hat. Die Gründe hierfür sind mannigfaltig: Von fest vorgegebenen Update-Zyklen bis hin
|
||||
zu Systeme mit speziellen Anpassungen, kann leider nicht davon ausgegangen werden, dass alle ePayBL-Systeme exakt gleich
|
||||
ansprechbar sind - auch wenn es sich dabei eigentlich um einen standardisierten Dienst handelt.
|
||||
|
||||
Aus diesem Grund gibt es mit dem ePayBL-Konnektor eine weitere Abstraktionsschicht welche optional zwischen den
|
||||
Fachverfahren und dem ePayBL-Server sitzt. Dieser Konnektor wird so gepflegt, dass er zum einen eine dauerhaft
|
||||
gleichartige Schnittstelle den Fachverfahren bietet aber gleichzeitig auch mit jeder Version des ePayBL-Servers
|
||||
kommunizieren kann - egal wie neu oder alt, wie regulär oder angepasst diese ist.
|
||||
|
||||
Im Grunde müsste daher eigentlich immer gesagt werden, dass pretix eine Anbindung an den ePayBL-Konnektor bietet; nicht
|
||||
an "ePayBL" oder den "ePayBL-Server". Diese Unterscheidung kann bei der Ersteinrichtung und Anforderung von Zugangsdaten
|
||||
von Relevanz sein. Da in der Praxis jedoch beide Begriffe gleichbedeutend genutzt werden, wird im Folgenden auch nur von
|
||||
einer ePayBL-Anbindung die Rede sein - auch wenn explizit der Konnektor gemeint ist.
|
||||
|
||||
|
||||
.. _`Kontierungsmodus`:
|
||||
|
||||
Kontierungsmodus
|
||||
----------------
|
||||
|
||||
ePayBL ist ein Produkt, welches für die Abwicklung von Online-Zahlungsvorgängen in der Verwaltung geschaffen wurde. Ein
|
||||
Umfeld, in dem klar definiert ist, was ein Kunde gerade bezahlt und wohin das Geld genau fließt. Diese Annahmen lassen
|
||||
sich in einem Ticketshop wie pretix jedoch nur teilweise genauso abbilden.
|
||||
|
||||
Die ePayBL-Integration für pretix bietet daher zwei unterschiedliche Modi an, wie Buchungen erfasst und an ePayBL und
|
||||
damit auch an die dahinterliegenden Haushaltssysteme gemeldet werden können.
|
||||
|
||||
Kontierung pro Position/Artikel
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Dieser Modus versucht den klassischen, behördentypischen ePayBL-Zahlungsvorgang abzubilden: Jede einzelne Position, die
|
||||
ein Kunde in den Warenkorb legt, wird auch genauso 1:1 an ePayBL und die Hintergrundsysteme übermittelt.
|
||||
|
||||
Hierbei muss zwingend auch für jede Position ein Kennzeichen für Haushaltsstelle und Objektnummer, sowie optional ein
|
||||
Kontierungsobjekt (``HREF``; bspw. ``stsl=Steuerschlüssel;psp=gsb:Geschäftsbereich,auft:Innenauftrag,kst:Kostenstelle;``
|
||||
) übermittelt werden.
|
||||
|
||||
Diese Daten sind vom Veranstalter entsprechend für jeden in der Veranstaltung angelegten Artikel innerhalb des Tabs
|
||||
"Zusätzliche Einstellungen" der Produkteinstellungen zu hinterlegen.
|
||||
|
||||
Während diese Einstellung eine größtmögliche Menge an Kontierungsdaten überträgt und auch ein separates Verbuchen von
|
||||
Leistungen auf unterschiedliche Haushaltsstellen erlaubt, so hat diese Option auch einen großen Nachteil: Der Kunde kann
|
||||
nur eine Zahlung für seine Bestellung leisten.
|
||||
|
||||
Während sich dies nicht nach einem großen Problem anhört, so kann dies beim Kunden zu Frust führen. pretix bietet die
|
||||
Option an, dass ein Veranstalter eine Bestellung jederzeit verändern kann: Ändern von Preisen von Positionen in einer
|
||||
aufgegebenen Bestellung, Zubuchen und Entfernen von Bestellpositionen, etc. Hat der Kunde seine ursprüngliche Bestellung
|
||||
jedoch schon bezahlt, kann pretix nicht mehr die komplette Bestellung mit den passenden Kontierungen übertragen - es
|
||||
müsste nur ein Differenz-Abbild zwischen Ursprungsbestellung und aktueller Bestellung übertragen werden. Aber auch wenn
|
||||
eine "Nachmeldung" möglich wäre, so wäre ein konkretes Auflösen für was jetzt genau gezahlt wird, nicht mehr möglich.
|
||||
|
||||
Daher gilt bei der Nutzung der Kontierung pro Position/Artikel: Der Kunde kann nur eine (erfolgreiche) Zahlung auf seine
|
||||
Bestellung leisten.
|
||||
|
||||
Eine weitere Einschränkung dieses Modus ist, dass aktuell keine Gebühren-Positionen (Versandkosten, Zahlungs-, Storno-
|
||||
oder Servicegebühren) in diesem Modus übertragen werden können. Bitte wenden Sie sich an uns, wenn Sie diese
|
||||
Funktionalität benötigen.
|
||||
|
||||
|
||||
Kontierung pro Zahlvorgang
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Dieser Modus verabschiedet sich vom behördlichen "Jede Position gehört genau zu einem Haushaltskonto und muss genau
|
||||
zugeordnet werden". Stattdessen werden alle Bestellpositionen - inklusive eventuell definierter Gebühren - vermengt und
|
||||
nur als ein großer Warenkorb, genauer gesagt: eine einzige Position an ePayBL sowie die Hintergrundsysteme gemeldet.
|
||||
|
||||
Während im "pro Postion/Artikel"-Modus jeder Artikel einzeln übermittelt wird und damit auch korrekt pro Artikel der
|
||||
jeweilige Brutto- und Nettopreis, sowie der anfallende Steuerbetrag und ein Steuerkennzeichen (mit Hilfe des optionalen
|
||||
``HREF``-Attributs) übermittelt werden, ist dies im "pro Zahlvorgang"-Modus nicht möglich.
|
||||
|
||||
Stattdessen übermittelt pretix nur einen Betrag für den gesamten Warenkorb: Bruttopreis == Nettopreis. Der Steuerbetrag
|
||||
wird hierbei als 0 übermittelt.
|
||||
|
||||
Die Angabe einer Haushaltsstelle und Objektnummer, sowie optional der ``HREF``-Kontierungsinformationen ist jedoch
|
||||
weiterhin notwendig - allerdings nicht mehr individuell für jeden Artikel/jede Position sondern nur für die gesamte
|
||||
Bestellung. Diese Daten sind direkt in den ePayBL-Einstellungen der Veranstaltung unter Einstellungen -> Zahlung ->
|
||||
ePayBL vorzunehmen
|
||||
|
||||
In der Praxis bedeutet dies, dass in einem angeschlossenen Haushaltssystem nicht nachvollzogen kann, welche Positionen
|
||||
konkret erworben und bezahlt wurden - stattdessen kann nur der Fakt, dass etwas verkauft wurde erfasst werden.
|
||||
|
||||
Je nach Aufbau und Vorgaben der Finanzbuchhaltung kann dies jedoch ausreichend sein - wenn bspw. eine Ferienfahrt
|
||||
angeboten wird und seitens der Haushaltssysteme nicht erfasst werden muss, wie viel vom Gesamtbetrag einer Bestellung
|
||||
auf die Ferienfahrt an sich, auf einen Zubringerbus und einen Satz Bettwäsche entfallen ist, sondern (vereinfacht
|
||||
gesagt) es ausreichend ist, dass "Eine Summe X für die Haushaltsstelle/Objektnummer geflossen ist".
|
||||
|
||||
Dieser Modus der Kontierung bietet Ihnen auch als Vorteil gegenüber dem vorhergehenden an, dass die Bestellungen der
|
||||
Kunden jederzeit erweitert und verändert werden können - auch wenn die Ursprungsbestellung schon bezahlt wurde und nur
|
||||
noch eine Differenz gezahlt wird.
|
||||
|
||||
|
||||
Einschränkungen
|
||||
---------------
|
||||
|
||||
Zum aktuellen Zeitpunkt erlaubt die pretix-Anbindung an ePayBL nicht das durchführen von Erstattungen von bereits
|
||||
geleisteten Zahlungen. Der Prozess hierfür unterscheidet sich von Behörde zu Behörde und muss daher händisch
|
||||
durchgeführt werden.
|
||||
|
||||
.. _ePayBL: https://www.epaybl.de/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -18,6 +18,7 @@ If you want to **create** a plugin, please go to the
|
||||
campaigns
|
||||
certificates
|
||||
digital
|
||||
epaybl
|
||||
exhibitors
|
||||
shipping
|
||||
imported_secrets
|
||||
|
||||
+3
-2
@@ -73,9 +73,10 @@ dependencies = [
|
||||
"packaging",
|
||||
"paypalrestsdk==1.13.*",
|
||||
"paypal-checkout-serversdk==1.0.*",
|
||||
"PyJWT==2.6.*",
|
||||
"PyJWT==2.7.*",
|
||||
"phonenumberslite==8.13.*",
|
||||
"Pillow==9.5.*",
|
||||
"pretix-plugin-build",
|
||||
"protobuf==4.23.*",
|
||||
"psycopg2-binary",
|
||||
"pycountry",
|
||||
@@ -91,7 +92,7 @@ dependencies = [
|
||||
"qrcode==7.4.*",
|
||||
"redis==4.5.*,>=4.5.4",
|
||||
"reportlab==4.0.*",
|
||||
"requests==2.30.*",
|
||||
"requests==2.31.*",
|
||||
"sentry-sdk==1.15.*",
|
||||
"sepaxml==2.6.*",
|
||||
"slimit",
|
||||
|
||||
@@ -29,7 +29,6 @@ sys.path.append(str(Path.cwd() / 'src'))
|
||||
|
||||
|
||||
def _CustomBuild(*args, **kwargs):
|
||||
print(sys.path)
|
||||
from pretix._build import CustomBuild
|
||||
return CustomBuild(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ def npm_install():
|
||||
|
||||
class CustomBuild(build):
|
||||
def run(self):
|
||||
if "src" not in os.listdir(".") or "pretix" not in os.listdir("src"):
|
||||
# Only run this command on the pretix module, not on other modules even if it's registered globally
|
||||
# in some cases
|
||||
return build.run(self)
|
||||
if "PRETIX_DOCKER_BUILD" in os.environ:
|
||||
return # this is a hack to allow calling this file early in our docker build to make use of caching
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix._build_settings")
|
||||
@@ -68,6 +72,10 @@ class CustomBuild(build):
|
||||
|
||||
class CustomBuildExt(build_ext):
|
||||
def run(self):
|
||||
if "src" not in os.listdir(".") or "pretix" not in os.listdir("src"):
|
||||
# Only run this command on the pretix module, not on other modules even if it's registered globally
|
||||
# in some cases
|
||||
return build_ext.run(self)
|
||||
if "PRETIX_DOCKER_BUILD" in os.environ:
|
||||
return # this is a hack to allow calling this file early in our docker build to make use of caching
|
||||
npm_install()
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import json
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
@@ -46,3 +48,16 @@ class AsymmetricField(serializers.Field):
|
||||
|
||||
def run_validation(self, data=serializers.empty):
|
||||
return self.write.run_validation(data)
|
||||
|
||||
|
||||
class CompatibleJSONField(serializers.JSONField):
|
||||
def to_internal_value(self, data):
|
||||
try:
|
||||
return json.dumps(data)
|
||||
except (TypeError, ValueError):
|
||||
self.fail('invalid')
|
||||
|
||||
def to_representation(self, value):
|
||||
if value:
|
||||
return json.loads(value)
|
||||
return value
|
||||
|
||||
@@ -46,6 +46,7 @@ from rest_framework import serializers
|
||||
from rest_framework.fields import ChoiceField, Field
|
||||
from rest_framework.relations import SlugRelatedField
|
||||
|
||||
from pretix.api.serializers import CompatibleJSONField
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.api.serializers.settings import SettingsSerializer
|
||||
from pretix.base.models import Device, Event, TaxRule, TeamAPIToken
|
||||
@@ -53,6 +54,7 @@ from pretix.base.models.event import SubEvent
|
||||
from pretix.base.models.items import (
|
||||
ItemMetaProperty, SubEventItem, SubEventItemVariation,
|
||||
)
|
||||
from pretix.base.models.tax import CustomRulesValidator
|
||||
from pretix.base.services.seating import (
|
||||
SeatProtected, generate_seats, validate_plan_change,
|
||||
)
|
||||
@@ -650,9 +652,16 @@ class SubEventSerializer(I18nAwareModelSerializer):
|
||||
|
||||
|
||||
class TaxRuleSerializer(CountryFieldMixin, I18nAwareModelSerializer):
|
||||
custom_rules = CompatibleJSONField(
|
||||
validators=[CustomRulesValidator()],
|
||||
required=False,
|
||||
allow_null=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = TaxRule
|
||||
fields = ('id', 'name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country', 'internal_name', 'keep_gross_if_rate_changes')
|
||||
fields = ('id', 'name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country', 'internal_name',
|
||||
'keep_gross_if_rate_changes', 'custom_rules')
|
||||
|
||||
|
||||
class EventSettingsSerializer(SettingsSerializer):
|
||||
|
||||
@@ -93,7 +93,7 @@ class JobRunSerializer(serializers.Serializer):
|
||||
if events is not None and not isinstance(ex, OrganizerLevelExportMixin):
|
||||
self.fields["events"] = serializers.SlugRelatedField(
|
||||
queryset=events,
|
||||
required=True,
|
||||
required=False,
|
||||
allow_empty=False,
|
||||
slug_field='slug',
|
||||
many=True
|
||||
@@ -156,8 +156,9 @@ class JobRunSerializer(serializers.Serializer):
|
||||
def to_internal_value(self, data):
|
||||
if isinstance(data, QueryDict):
|
||||
data = data.copy()
|
||||
|
||||
for k, v in self.fields.items():
|
||||
if isinstance(v, serializers.ManyRelatedField) and k not in data:
|
||||
if isinstance(v, serializers.ManyRelatedField) and k not in data and k != "events":
|
||||
data[k] = []
|
||||
|
||||
for fk in self.fields.keys():
|
||||
|
||||
@@ -60,6 +60,8 @@ class NestedGiftCardSerializer(GiftCardSerializer):
|
||||
|
||||
|
||||
class ReusableMediaSerializer(I18nAwareModelSerializer):
|
||||
organizer = serializers.SlugRelatedField(slug_field='slug', read_only=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -111,6 +113,7 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
||||
model = ReusableMedium
|
||||
fields = (
|
||||
'id',
|
||||
'organizer',
|
||||
'created',
|
||||
'updated',
|
||||
'type',
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from collections import Counter, defaultdict
|
||||
@@ -39,6 +38,7 @@ from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.relations import SlugRelatedField
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from pretix.api.serializers import CompatibleJSONField
|
||||
from pretix.api.serializers.event import SubEventSerializer
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.api.serializers.item import (
|
||||
@@ -896,19 +896,6 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
return data
|
||||
|
||||
|
||||
class CompatibleJSONField(serializers.JSONField):
|
||||
def to_internal_value(self, data):
|
||||
try:
|
||||
return json.dumps(data)
|
||||
except (TypeError, ValueError):
|
||||
self.fail('invalid')
|
||||
|
||||
def to_representation(self, value):
|
||||
if value:
|
||||
return json.loads(value)
|
||||
return value
|
||||
|
||||
|
||||
class WrappedList:
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
|
||||
@@ -36,9 +36,9 @@ from pretix.api.serializers.settings import SettingsSerializer
|
||||
from pretix.base.auth import get_auth_backends
|
||||
from pretix.base.i18n import get_language_without_region
|
||||
from pretix.base.models import (
|
||||
Customer, Device, GiftCard, GiftCardTransaction, Membership,
|
||||
MembershipType, OrderPosition, Organizer, ReusableMedium, SeatingPlan,
|
||||
Team, TeamAPIToken, TeamInvite, User,
|
||||
Customer, Device, GiftCard, GiftCardAcceptance, GiftCardTransaction,
|
||||
Membership, MembershipType, OrderPosition, Organizer, ReusableMedium,
|
||||
SeatingPlan, Team, TeamAPIToken, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.models.seating import SeatingPlanLayoutValidator
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
@@ -183,8 +183,11 @@ class GiftCardSerializer(I18nAwareModelSerializer):
|
||||
qs = GiftCard.objects.filter(
|
||||
secret=s
|
||||
).filter(
|
||||
Q(issuer=self.context["organizer"]) | Q(
|
||||
issuer__gift_card_collector_acceptance__collector=self.context["organizer"])
|
||||
Q(issuer=self.context["organizer"]) |
|
||||
Q(issuer__in=GiftCardAcceptance.objects.filter(
|
||||
acceptor=self.context["organizer"],
|
||||
active=True,
|
||||
).values_list('issuer', flat=True))
|
||||
)
|
||||
if self.instance:
|
||||
qs = qs.exclude(pk=self.instance.pk)
|
||||
|
||||
@@ -396,7 +396,7 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
||||
|
||||
def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force, checkin_type, ignore_unpaid, nonce,
|
||||
untrusted_input, user, auth, expand, pdf_data, request, questions_supported, canceled_supported,
|
||||
source_type='barcode', legacy_url_support=False):
|
||||
source_type='barcode', legacy_url_support=False, simulate=False):
|
||||
if not checkinlists:
|
||||
raise ValidationError('No check-in list passed.')
|
||||
|
||||
@@ -433,6 +433,8 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
)
|
||||
raw_barcode_for_checkin = None
|
||||
from_revoked_secret = False
|
||||
if simulate:
|
||||
common_checkin_args['__fake_arg_to_prevent_this_from_being_saved'] = True
|
||||
|
||||
# 1. Gather a list of positions that could be the one we looking for, either from their ID, secret or
|
||||
# parent secret
|
||||
@@ -472,13 +474,14 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
revoked_matches = list(
|
||||
RevokedTicketSecret.objects.filter(event_id__in=list_by_event.keys(), secret=raw_barcode))
|
||||
if len(revoked_matches) == 0:
|
||||
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': checkinlists[0].pk,
|
||||
'barcode': raw_barcode,
|
||||
'searched_lists': [cl.pk for cl in checkinlists]
|
||||
}, user=user, auth=auth)
|
||||
if not simulate:
|
||||
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': checkinlists[0].pk,
|
||||
'barcode': raw_barcode,
|
||||
'searched_lists': [cl.pk for cl in checkinlists]
|
||||
}, user=user, auth=auth)
|
||||
|
||||
for cl in checkinlists:
|
||||
for k, s in cl.event.ticket_secret_generators.items():
|
||||
@@ -492,12 +495,13 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
except:
|
||||
pass
|
||||
|
||||
Checkin.objects.create(
|
||||
position=None,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_INVALID,
|
||||
**common_checkin_args,
|
||||
)
|
||||
if not simulate:
|
||||
Checkin.objects.create(
|
||||
position=None,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_INVALID,
|
||||
**common_checkin_args,
|
||||
)
|
||||
|
||||
if force and legacy_url_support and isinstance(auth, Device):
|
||||
# There was a bug in libpretixsync: If you scanned a ticket in offline mode that was
|
||||
@@ -539,19 +543,20 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
from_revoked_secret = True
|
||||
else:
|
||||
op = revoked_matches[0].position
|
||||
op.order.log_action('pretix.event.checkin.revoked', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[revoked_matches[0].event_id].pk,
|
||||
'barcode': raw_barcode
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[revoked_matches[0].event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_REVOKED,
|
||||
**common_checkin_args
|
||||
)
|
||||
if not simulate:
|
||||
op.order.log_action('pretix.event.checkin.revoked', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[revoked_matches[0].event_id].pk,
|
||||
'barcode': raw_barcode
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[revoked_matches[0].event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_REVOKED,
|
||||
**common_checkin_args
|
||||
)
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_REVOKED,
|
||||
@@ -588,24 +593,25 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
# We choose the first match (regardless of product) for the logging since it's most likely to be the
|
||||
# base product according to our order_by above.
|
||||
op = op_candidates[0]
|
||||
op.order.log_action('pretix.event.checkin.denied', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'errorcode': Checkin.REASON_AMBIGUOUS,
|
||||
'reason_explanation': None,
|
||||
'force': force,
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[op.order.event_id].pk,
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[op.order.event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_AMBIGUOUS,
|
||||
error_explanation=None,
|
||||
**common_checkin_args,
|
||||
)
|
||||
if not simulate:
|
||||
op.order.log_action('pretix.event.checkin.denied', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'errorcode': Checkin.REASON_AMBIGUOUS,
|
||||
'reason_explanation': None,
|
||||
'force': force,
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[op.order.event_id].pk,
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[op.order.event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_AMBIGUOUS,
|
||||
error_explanation=None,
|
||||
**common_checkin_args,
|
||||
)
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_AMBIGUOUS,
|
||||
@@ -652,6 +658,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
raw_barcode=raw_barcode_for_checkin,
|
||||
raw_source_type=source_type,
|
||||
from_revoked_secret=from_revoked_secret,
|
||||
simulate=simulate,
|
||||
)
|
||||
except RequiredQuestionsError as e:
|
||||
return Response({
|
||||
@@ -664,23 +671,24 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
}, status=400)
|
||||
except CheckInError as e:
|
||||
op.order.log_action('pretix.event.checkin.denied', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'errorcode': e.code,
|
||||
'reason_explanation': e.reason,
|
||||
'force': force,
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[op.order.event_id].pk,
|
||||
}, user=user, auth=auth)
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=e.code,
|
||||
error_explanation=e.reason,
|
||||
**common_checkin_args,
|
||||
)
|
||||
if not simulate:
|
||||
op.order.log_action('pretix.event.checkin.denied', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'errorcode': e.code,
|
||||
'reason_explanation': e.reason,
|
||||
'force': force,
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[op.order.event_id].pk,
|
||||
}, user=user, auth=auth)
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=e.code,
|
||||
error_explanation=e.reason,
|
||||
**common_checkin_args,
|
||||
)
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': e.code,
|
||||
|
||||
@@ -71,6 +71,8 @@ with scopes_disabled():
|
||||
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
|
||||
sales_channel = django_filters.rest_framework.CharFilter(method='sales_channel_qs')
|
||||
search = django_filters.rest_framework.CharFilter(method='search_qs')
|
||||
date_from = django_filters.rest_framework.IsoDateTimeFromToRangeFilter()
|
||||
date_to = django_filters.rest_framework.IsoDateTimeFromToRangeFilter()
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
@@ -336,6 +338,8 @@ with scopes_disabled():
|
||||
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
|
||||
sales_channel = django_filters.rest_framework.CharFilter(method='sales_channel_qs')
|
||||
search = django_filters.rest_framework.CharFilter(method='search_qs')
|
||||
date_from = django_filters.rest_framework.IsoDateTimeFromToRangeFilter()
|
||||
date_to = django_filters.rest_framework.IsoDateTimeFromToRangeFilter()
|
||||
|
||||
class Meta:
|
||||
model = SubEvent
|
||||
|
||||
@@ -133,7 +133,12 @@ class EventExportersViewSet(ExportersMixin, viewsets.ViewSet):
|
||||
def exporters(self):
|
||||
exporters = []
|
||||
responses = register_data_exporters.send(self.request.event)
|
||||
for ex in sorted([response(self.request.event, self.request.organizer) for r, response in responses if response], key=lambda ex: str(ex.verbose_name)):
|
||||
raw_exporters = [response(self.request.event, self.request.organizer) for r, response in responses if response]
|
||||
raw_exporters = [
|
||||
ex for ex in raw_exporters
|
||||
if ex.available_for_user(self.request.user if self.request.user and self.request.user.is_authenticated else None)
|
||||
]
|
||||
for ex in sorted(raw_exporters, key=lambda ex: str(ex.verbose_name)):
|
||||
ex._serializer = JobRunSerializer(exporter=ex)
|
||||
exporters.append(ex)
|
||||
return exporters
|
||||
@@ -166,7 +171,7 @@ class OrganizerExportersViewSet(ExportersMixin, viewsets.ViewSet):
|
||||
if (
|
||||
not isinstance(ex, OrganizerLevelExportMixin) or
|
||||
perm_holder.has_organizer_permission(self.request.organizer, ex.organizer_required_permission, self.request)
|
||||
)
|
||||
) and ex.available_for_user(self.request.user if self.request.user and self.request.user.is_authenticated else None)
|
||||
]
|
||||
for ex in sorted(raw_exporters, key=lambda ex: str(ex.verbose_name)):
|
||||
ex._serializer = JobRunSerializer(exporter=ex, events=events)
|
||||
|
||||
@@ -39,7 +39,8 @@ from pretix.api.serializers.media import (
|
||||
)
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import (
|
||||
Checkin, GiftCard, GiftCardTransaction, OrderPosition, ReusableMedium,
|
||||
Checkin, GiftCard, GiftCardAcceptance, GiftCardTransaction, OrderPosition,
|
||||
ReusableMedium,
|
||||
)
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
@@ -135,12 +136,28 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
except ReusableMedium.DoesNotExist:
|
||||
mt = MEDIA_TYPES.get(s.validated_data["type"])
|
||||
if mt:
|
||||
m = mt.handle_unknown(request.organizer, s.validated_data["identifier"], request.user, request.auth)
|
||||
if m:
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
try:
|
||||
with scopes_disabled():
|
||||
m = ReusableMedium.objects.get(
|
||||
organizer__in=GiftCardAcceptance.objects.filter(
|
||||
acceptor=request.organizer,
|
||||
active=True,
|
||||
reusable_media=True,
|
||||
).values_list('issuer', flat=True),
|
||||
type=s.validated_data["type"],
|
||||
identifier=s.validated_data["identifier"],
|
||||
)
|
||||
m.linked_orderposition = None # not relevant for cross-organizer
|
||||
m.customer = None # not relevant for cross-organizer
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
except ReusableMedium.DoesNotExist:
|
||||
mt = MEDIA_TYPES.get(s.validated_data["type"])
|
||||
if mt:
|
||||
m = mt.handle_unknown(request.organizer, s.validated_data["identifier"], request.user, request.auth)
|
||||
if m:
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
|
||||
return Response({"result": None})
|
||||
|
||||
|
||||
@@ -661,7 +661,16 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
|
||||
with language(order.locale, self.request.event.settings.region):
|
||||
payment = order.payments.last()
|
||||
|
||||
# OrderCreateSerializer creates at most one payment
|
||||
if payment and payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED:
|
||||
order.log_action(
|
||||
'pretix.event.order.payment.confirmed', {
|
||||
'local_id': payment.local_id,
|
||||
'provider': payment.provider,
|
||||
},
|
||||
user=request.user if request.user.is_authenticated else None,
|
||||
auth=request.auth,
|
||||
)
|
||||
order_placed.send(self.request.event, order=order)
|
||||
if order.status == Order.STATUS_PAID:
|
||||
order_paid.send(self.request.event, order=order)
|
||||
|
||||
@@ -189,6 +189,19 @@ class ParametrizedOrderPositionWebhookEvent(ParametrizedOrderWebhookEvent):
|
||||
return d
|
||||
|
||||
|
||||
class ParametrizedWaitingListEntryWebhookEvent(ParametrizedWebhookEvent):
|
||||
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
# do not use content_object, this is also called in deletion
|
||||
return {
|
||||
'notification_id': logentry.pk,
|
||||
'organizer': logentry.event.organizer.slug,
|
||||
'event': logentry.event.slug,
|
||||
'waitinglistentry': logentry.object_id,
|
||||
'action': logentry.action_type,
|
||||
}
|
||||
|
||||
|
||||
@receiver(register_webhook_events, dispatch_uid="base_register_default_webhook_events")
|
||||
def register_default_webhook_events(sender, **kwargs):
|
||||
return (
|
||||
@@ -321,6 +334,22 @@ def register_default_webhook_events(sender, **kwargs):
|
||||
'pretix.event.testmode.deactivated',
|
||||
_('Test-Mode of shop has been deactivated'),
|
||||
),
|
||||
ParametrizedWaitingListEntryWebhookEvent(
|
||||
'pretix.event.orders.waitinglist.added',
|
||||
_('Waiting list entry added'),
|
||||
),
|
||||
ParametrizedWaitingListEntryWebhookEvent(
|
||||
'pretix.event.orders.waitinglist.changed',
|
||||
_('Waiting list entry changed'),
|
||||
),
|
||||
ParametrizedWaitingListEntryWebhookEvent(
|
||||
'pretix.event.orders.waitinglist.deleted',
|
||||
_('Waiting list entry deleted'),
|
||||
),
|
||||
ParametrizedWaitingListEntryWebhookEvent(
|
||||
'pretix.event.orders.waitinglist.voucher_assigned',
|
||||
_('Waiting list entry received voucher'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -157,6 +157,13 @@ class BaseExporter:
|
||||
"""
|
||||
raise NotImplementedError() # NOQA
|
||||
|
||||
def available_for_user(self, user) -> bool:
|
||||
"""
|
||||
Allows to do additional checks whether an exporter is available based on the user who calls it. Note that
|
||||
``user`` may be ``None`` e.g. during API usage.
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
class OrganizerLevelExportMixin:
|
||||
@property
|
||||
|
||||
@@ -850,6 +850,8 @@ class TransactionListExporter(ListExporter):
|
||||
_('Tax rule ID'),
|
||||
_('Tax rule'),
|
||||
_('Tax value'),
|
||||
_('Gross total'),
|
||||
_('Tax total'),
|
||||
]
|
||||
|
||||
if form_data.get('_format') == 'xlsx':
|
||||
@@ -901,6 +903,8 @@ class TransactionListExporter(ListExporter):
|
||||
t.tax_rule_id or '',
|
||||
str(t.tax_rule.internal_name or t.tax_rule.name) if t.tax_rule_id else '',
|
||||
t.tax_value,
|
||||
t.price * t.count,
|
||||
t.tax_value * t.count,
|
||||
]
|
||||
|
||||
if form_data.get('_format') == 'xlsx':
|
||||
@@ -1143,7 +1147,7 @@ class GiftcardTransactionListExporter(OrganizerLevelExportMixin, ListExporter):
|
||||
def iterate_list(self, form_data):
|
||||
qs = GiftCardTransaction.objects.filter(
|
||||
card__issuer=self.organizer,
|
||||
).order_by('datetime').select_related('card', 'order', 'order__event')
|
||||
).order_by('datetime').select_related('card', 'order', 'order__event', 'acceptor')
|
||||
|
||||
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)
|
||||
@@ -1159,6 +1163,7 @@ class GiftcardTransactionListExporter(OrganizerLevelExportMixin, ListExporter):
|
||||
_('Amount'),
|
||||
_('Currency'),
|
||||
_('Order'),
|
||||
_('Organizer'),
|
||||
]
|
||||
yield headers
|
||||
|
||||
@@ -1170,6 +1175,7 @@ class GiftcardTransactionListExporter(OrganizerLevelExportMixin, ListExporter):
|
||||
obj.value,
|
||||
obj.card.currency,
|
||||
obj.order.full_code if obj.order else None,
|
||||
str(obj.acceptor or ""),
|
||||
]
|
||||
yield row
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ from django.utils.timezone import get_current_timezone, now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_countries import countries
|
||||
from django_countries.fields import Country, CountryField
|
||||
from geoip2.errors import AddressNotFoundError
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from phonenumber_field.phonenumber import PhoneNumber
|
||||
from phonenumber_field.widgets import PhoneNumberPrefixWidget
|
||||
@@ -356,9 +357,12 @@ class WrappedPhoneNumberPrefixWidget(PhoneNumberPrefixWidget):
|
||||
def guess_country_from_request(request, event):
|
||||
if settings.HAS_GEOIP:
|
||||
g = GeoIP2()
|
||||
res = g.country(get_client_ip(request))
|
||||
if res['country_code'] and len(res['country_code']) == 2:
|
||||
return Country(res['country_code'])
|
||||
try:
|
||||
res = g.country(get_client_ip(request))
|
||||
if res['country_code'] and len(res['country_code']) == 2:
|
||||
return Country(res['country_code'])
|
||||
except AddressNotFoundError:
|
||||
pass
|
||||
return guess_country(event)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 3.2.18 on 2023-05-12 10:08
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0241_itemmetaproperties_required_values'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='giftcardacceptance',
|
||||
old_name='collector',
|
||||
new_name='acceptor',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='giftcardacceptance',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='giftcardacceptance',
|
||||
name='reusable_media',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='giftcardacceptance',
|
||||
name='issuer',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gift_card_acceptor_acceptance', to='pretixbase.organizer'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='giftcardacceptance',
|
||||
unique_together={('issuer', 'acceptor')},
|
||||
),
|
||||
]
|
||||
@@ -46,14 +46,19 @@ def gen_giftcard_secret(length=8):
|
||||
class GiftCardAcceptance(models.Model):
|
||||
issuer = models.ForeignKey(
|
||||
'Organizer',
|
||||
related_name='gift_card_collector_acceptance',
|
||||
related_name='gift_card_acceptor_acceptance',
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
collector = models.ForeignKey(
|
||||
acceptor = models.ForeignKey(
|
||||
'Organizer',
|
||||
related_name='gift_card_issuer_acceptance',
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
active = models.BooleanField(default=True)
|
||||
reusable_media = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
unique_together = (('issuer', 'acceptor'),)
|
||||
|
||||
|
||||
class GiftCard(LoggedModel):
|
||||
@@ -114,7 +119,7 @@ class GiftCard(LoggedModel):
|
||||
return self.transactions.aggregate(s=Sum('value'))['s'] or Decimal('0.00')
|
||||
|
||||
def accepted_by(self, organizer):
|
||||
return self.issuer == organizer or GiftCardAcceptance.objects.filter(issuer=self.issuer, collector=organizer).exists()
|
||||
return self.issuer == organizer or GiftCardAcceptance.objects.filter(issuer=self.issuer, acceptor=organizer, active=True).exists()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.secret:
|
||||
|
||||
@@ -40,7 +40,7 @@ from django.conf import settings
|
||||
from django.core.mail import get_connection
|
||||
from django.core.validators import MinLengthValidator, RegexValidator
|
||||
from django.db import models
|
||||
from django.db.models import Exists, OuterRef, Q
|
||||
from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.functional import cached_property
|
||||
@@ -157,17 +157,19 @@ class Organizer(LoggedModel):
|
||||
return self.cache.get_or_set(
|
||||
key='has_gift_cards',
|
||||
timeout=15,
|
||||
default=lambda: self.issued_gift_cards.exists() or self.gift_card_issuer_acceptance.exists()
|
||||
default=lambda: self.issued_gift_cards.exists() or self.gift_card_issuer_acceptance.filter(active=True).exists()
|
||||
)
|
||||
|
||||
@property
|
||||
def accepted_gift_cards(self):
|
||||
from .giftcards import GiftCard, GiftCardAcceptance
|
||||
|
||||
return GiftCard.objects.annotate(
|
||||
accepted=Exists(GiftCardAcceptance.objects.filter(issuer=OuterRef('issuer'), collector=self))
|
||||
).filter(
|
||||
Q(issuer=self) | Q(accepted=True)
|
||||
return GiftCard.objects.filter(
|
||||
Q(issuer=self) |
|
||||
Q(issuer__in=GiftCardAcceptance.objects.filter(
|
||||
acceptor=self,
|
||||
active=True,
|
||||
).values_list('issuer', flat=True))
|
||||
)
|
||||
|
||||
@property
|
||||
|
||||
@@ -22,9 +22,12 @@
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
import jsonschema
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.utils.deconstruct import deconstructible
|
||||
from django.utils.formats import localize
|
||||
from django.utils.translation import gettext_lazy as _, pgettext
|
||||
from i18nfield.fields import I18nCharField
|
||||
@@ -135,6 +138,25 @@ def cc_to_vat_prefix(country_code):
|
||||
return country_code
|
||||
|
||||
|
||||
@deconstructible
|
||||
class CustomRulesValidator:
|
||||
def __call__(self, value):
|
||||
if not isinstance(value, dict):
|
||||
try:
|
||||
val = json.loads(value)
|
||||
except ValueError:
|
||||
raise ValidationError(_('Your layout file is not a valid JSON file.'))
|
||||
else:
|
||||
val = value
|
||||
with open(finders.find('schema/tax-rules-custom.schema.json'), 'r') as f:
|
||||
schema = json.loads(f.read())
|
||||
try:
|
||||
jsonschema.validate(val, schema)
|
||||
except jsonschema.ValidationError as e:
|
||||
e = str(e).replace('%', '%%')
|
||||
raise ValidationError(_('Your set of rules is not valid. Error message: {}').format(e))
|
||||
|
||||
|
||||
class TaxRule(LoggedModel):
|
||||
event = models.ForeignKey('Event', related_name='tax_rules', on_delete=models.CASCADE)
|
||||
internal_name = models.CharField(
|
||||
|
||||
@@ -218,7 +218,7 @@ class WaitingListEntry(LoggedModel):
|
||||
'waitinglistentry': self.pk,
|
||||
'subevent': self.subevent.pk if self.subevent else None,
|
||||
}, user=user, auth=auth)
|
||||
self.log_action('pretix.waitinglist.voucher', user=user, auth=auth)
|
||||
self.log_action('pretix.event.orders.waitinglist.voucher_assigned', user=user, auth=auth)
|
||||
self.voucher = v
|
||||
self.save()
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ from django.utils.translation import gettext as _
|
||||
from django_scopes import scope, scopes_disabled
|
||||
|
||||
from pretix.base.models import (
|
||||
Checkin, CheckinList, Device, Order, OrderPosition, QuestionOption,
|
||||
Checkin, CheckinList, Device, Event, ItemVariation, Order, OrderPosition,
|
||||
QuestionOption,
|
||||
)
|
||||
from pretix.base.signals import checkin_created, order_placed, periodic_task
|
||||
from pretix.helpers import OF_SELF
|
||||
@@ -65,12 +66,13 @@ from pretix.helpers.jsonlogic_query import (
|
||||
)
|
||||
|
||||
|
||||
def _build_time(t=None, value=None, ev=None):
|
||||
def _build_time(t=None, value=None, ev=None, now_dt=None):
|
||||
now_dt = now_dt or now()
|
||||
if t == "custom":
|
||||
return dateutil.parser.parse(value)
|
||||
elif t == "customtime":
|
||||
parsed = dateutil.parser.parse(value)
|
||||
return now().astimezone(ev.timezone).replace(
|
||||
return now_dt.astimezone(ev.timezone).replace(
|
||||
hour=parsed.hour,
|
||||
minute=parsed.minute,
|
||||
second=parsed.second,
|
||||
@@ -84,7 +86,42 @@ def _build_time(t=None, value=None, ev=None):
|
||||
return ev.date_admission or ev.date_from
|
||||
|
||||
|
||||
def _logic_explain(rules, ev, rule_data):
|
||||
def _logic_annotate_for_graphic_explain(rules, ev, rule_data):
|
||||
logic_environment = _get_logic_environment(ev)
|
||||
event = ev if isinstance(ev, Event) else ev.event
|
||||
|
||||
def _evaluate_inners(r):
|
||||
if not isinstance(r, dict):
|
||||
return r
|
||||
operator = list(r.keys())[0]
|
||||
values = r[operator]
|
||||
if operator in ("and", "or"):
|
||||
return {operator: [_evaluate_inners(v) for v in values]}
|
||||
result = logic_environment.apply(r, rule_data)
|
||||
return {**r, '__result': result}
|
||||
|
||||
def _add_var_values(r):
|
||||
if not isinstance(r, dict):
|
||||
return r
|
||||
operator = [k for k in r.keys() if not k.startswith("__")][0]
|
||||
values = r[operator]
|
||||
if operator == "var":
|
||||
var = values[0] if isinstance(values, list) else values
|
||||
val = rule_data[var]
|
||||
if var == "product":
|
||||
val = str(event.items.get(pk=val))
|
||||
elif var == "variation":
|
||||
val = str(ItemVariation.objects.get(item__event=event, pk=val))
|
||||
elif isinstance(val, datetime):
|
||||
val = date_format(val.astimezone(ev.timezone), "SHORT_DATETIME_FORMAT")
|
||||
return {"var": var, "__result": val}
|
||||
else:
|
||||
return {**r, operator: [_add_var_values(v) for v in values]}
|
||||
|
||||
return _add_var_values(_evaluate_inners(rules))
|
||||
|
||||
|
||||
def _logic_explain(rules, ev, rule_data, now_dt=None):
|
||||
"""
|
||||
Explains when the logic denied the check-in. Only works for a denied check-in.
|
||||
|
||||
@@ -114,6 +151,7 @@ def _logic_explain(rules, ev, rule_data):
|
||||
Additionally, we favor a "close failure". Therefore, in the above example, we'd show "You can only
|
||||
get in before 17:00". In the middle of the night it would switch to "You can only get in after 09:00".
|
||||
"""
|
||||
now_dt = now_dt or now()
|
||||
logic_environment = _get_logic_environment(ev)
|
||||
_var_values = {'False': False, 'True': True}
|
||||
_var_explanations = {}
|
||||
@@ -198,9 +236,9 @@ def _logic_explain(rules, ev, rule_data):
|
||||
else:
|
||||
compare_to -= tolerance
|
||||
|
||||
var_weights[vname] = (200, abs(now() - compare_to).total_seconds())
|
||||
var_weights[vname] = (200, abs(now_dt - compare_to).total_seconds())
|
||||
|
||||
if abs(now() - compare_to) < timedelta(hours=12):
|
||||
if abs(now_dt - compare_to) < timedelta(hours=12):
|
||||
compare_to_text = date_format(compare_to, 'TIME_FORMAT')
|
||||
else:
|
||||
compare_to_text = date_format(compare_to, 'SHORT_DATETIME_FORMAT')
|
||||
@@ -357,7 +395,7 @@ class LazyRuleVars:
|
||||
@cached_property
|
||||
def entries_today(self):
|
||||
tz = self._clist.event.timezone
|
||||
midnight = now().astimezone(tz).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
midnight = self._dt.astimezone(tz).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
return self._position.checkins.filter(type=Checkin.TYPE_ENTRY, list=self._clist, datetime__gte=midnight).count()
|
||||
|
||||
@cached_property
|
||||
@@ -378,7 +416,7 @@ class LazyRuleVars:
|
||||
# between platforms (None<1 is true on some, but not all), we rather choose something that is at least
|
||||
# consistent.
|
||||
return -1
|
||||
return (now() - last_entry.datetime).total_seconds() // 60
|
||||
return (self._dt - last_entry.datetime).total_seconds() // 60
|
||||
|
||||
@cached_property
|
||||
def minutes_since_first_entry(self):
|
||||
@@ -390,7 +428,7 @@ class LazyRuleVars:
|
||||
# between platforms (None<1 is true on some, but not all), we rather choose something that is at least
|
||||
# consistent.
|
||||
return -1
|
||||
return (now() - last_entry.datetime).total_seconds() // 60
|
||||
return (self._dt - last_entry.datetime).total_seconds() // 60
|
||||
|
||||
|
||||
class SQLLogic:
|
||||
@@ -693,7 +731,7 @@ def _save_answers(op, answers, given_answers):
|
||||
def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict, force=False,
|
||||
ignore_unpaid=False, nonce=None, datetime=None, questions_supported=True,
|
||||
user=None, auth=None, canceled_supported=False, type=Checkin.TYPE_ENTRY,
|
||||
raw_barcode=None, raw_source_type=None, from_revoked_secret=False):
|
||||
raw_barcode=None, raw_source_type=None, from_revoked_secret=False, simulate=False):
|
||||
"""
|
||||
Create a checkin for this particular order position and check-in list. Fails with CheckInError if the check in is
|
||||
not valid at this time.
|
||||
@@ -707,6 +745,7 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
:param questions_supported: When set to False, questions are ignored
|
||||
:param nonce: A random nonce to prevent race conditions.
|
||||
:param datetime: The datetime of the checkin, defaults to now.
|
||||
:param simulate: If true, the check-in is not saved.
|
||||
"""
|
||||
|
||||
# !!!!!!!!!
|
||||
@@ -734,7 +773,7 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
'blocked'
|
||||
)
|
||||
|
||||
if type != Checkin.TYPE_EXIT and op.valid_from and op.valid_from > now():
|
||||
if type != Checkin.TYPE_EXIT and op.valid_from and op.valid_from > dt:
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
@@ -748,7 +787,7 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
),
|
||||
)
|
||||
|
||||
if type != Checkin.TYPE_EXIT and op.valid_until and op.valid_until < now():
|
||||
if type != Checkin.TYPE_EXIT and op.valid_until and op.valid_until < dt:
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
@@ -773,7 +812,8 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
if q not in given_answers and q not in answers:
|
||||
require_answers.append(q)
|
||||
|
||||
_save_answers(op, answers, given_answers)
|
||||
if not simulate:
|
||||
_save_answers(op, answers, given_answers)
|
||||
|
||||
with transaction.atomic():
|
||||
# Lock order positions, if it is an entry. We don't need it for exits, as a race condition wouldn't be problematic
|
||||
@@ -859,30 +899,33 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
return
|
||||
|
||||
if entry_allowed or force:
|
||||
ci = Checkin.objects.create(
|
||||
position=op,
|
||||
type=type,
|
||||
list=clist,
|
||||
datetime=dt,
|
||||
device=device,
|
||||
gate=device.gate if device else None,
|
||||
nonce=nonce,
|
||||
forced=force and (not entry_allowed or from_revoked_secret or force_used),
|
||||
force_sent=force,
|
||||
raw_barcode=raw_barcode,
|
||||
raw_source_type=raw_source_type,
|
||||
)
|
||||
op.order.log_action('pretix.event.checkin', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'first': True,
|
||||
'forced': force or op.order.status != Order.STATUS_PAID,
|
||||
'datetime': dt,
|
||||
'type': type,
|
||||
'answers': {k.pk: str(v) for k, v in given_answers.items()},
|
||||
'list': clist.pk
|
||||
}, user=user, auth=auth)
|
||||
checkin_created.send(op.order.event, checkin=ci)
|
||||
if simulate:
|
||||
return True
|
||||
else:
|
||||
ci = Checkin.objects.create(
|
||||
position=op,
|
||||
type=type,
|
||||
list=clist,
|
||||
datetime=dt,
|
||||
device=device,
|
||||
gate=device.gate if device else None,
|
||||
nonce=nonce,
|
||||
forced=force and (not entry_allowed or from_revoked_secret or force_used),
|
||||
force_sent=force,
|
||||
raw_barcode=raw_barcode,
|
||||
raw_source_type=raw_source_type,
|
||||
)
|
||||
op.order.log_action('pretix.event.checkin', data={
|
||||
'position': op.id,
|
||||
'positionid': op.positionid,
|
||||
'first': True,
|
||||
'forced': force or op.order.status != Order.STATUS_PAID,
|
||||
'datetime': dt,
|
||||
'type': type,
|
||||
'answers': {k.pk: str(v) for k, v in given_answers.items()},
|
||||
'list': clist.pk
|
||||
}, user=user, auth=auth)
|
||||
checkin_created.send(op.order.event, checkin=ci)
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This ticket has already been redeemed.'),
|
||||
|
||||
@@ -290,6 +290,8 @@ def scheduled_organizer_export(self, organizer: Organizer, schedule: int) -> Non
|
||||
if isinstance(exporter, OrganizerLevelExportMixin):
|
||||
if not schedule.owner.has_organizer_permission(organizer, exporter.organizer_required_permission):
|
||||
has_permission = False
|
||||
if exporter and not exporter.available_for_user(schedule.owner):
|
||||
has_permission = False
|
||||
|
||||
_run_scheduled_export(
|
||||
schedule,
|
||||
|
||||
+67
-62
@@ -2018,8 +2018,8 @@ to your order for {event}.
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_resend_all_links': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2034,8 +2034,8 @@ The list is as follows:
|
||||
|
||||
{orders}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_free_attendee': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2050,8 +2050,8 @@ you have been registered for {event} successfully.
|
||||
You can view the details and status of your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_send_order_free_attendee': {
|
||||
'type': bool,
|
||||
@@ -2071,8 +2071,8 @@ no payment is required.
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_placed_require_approval': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2089,8 +2089,8 @@ be patient and wait for our next email.
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_placed': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2108,8 +2108,8 @@ of {total_with_currency}. Please complete your payment before {expire_date}.
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_attachment_new_order': {
|
||||
'default': None,
|
||||
@@ -2119,11 +2119,14 @@ Your {event} team"""))
|
||||
label=_('Attachment for new orders'),
|
||||
ext_whitelist=(".pdf",),
|
||||
max_size=settings.FILE_UPLOAD_MAX_SIZE_EMAIL_AUTO_ATTACHMENT,
|
||||
help_text=_('This file will be attached to the first email that we send for every new order. Therefore it will be '
|
||||
'combined with the "Placed order", "Free order", or "Received order" texts from above. It will be sent '
|
||||
'to both order contacts and attendees. You can use this e.g. to send your terms of service. Do not use '
|
||||
'it to send non-public information as this file might be sent before payment is confirmed or the order '
|
||||
'is approved. To avoid this vital email going to spam, you can only upload PDF files of up to {size} MB.').format(
|
||||
help_text=format_lazy(
|
||||
_(
|
||||
'This file will be attached to the first email that we send for every new order. Therefore it will be '
|
||||
'combined with the "Placed order", "Free order", or "Received order" texts from above. It will be sent '
|
||||
'to both order contacts and attendees. You can use this e.g. to send your terms of service. Do not use '
|
||||
'it to send non-public information as this file might be sent before payment is confirmed or the order '
|
||||
'is approved. To avoid this vital email going to spam, you can only upload PDF files of up to {size} MB.'
|
||||
),
|
||||
size=settings.FILE_UPLOAD_MAX_SIZE_EMAIL_AUTO_ATTACHMENT // (1024 * 1024),
|
||||
)
|
||||
),
|
||||
@@ -2152,8 +2155,8 @@ a ticket for {event} has been ordered for you.
|
||||
You can view the details and status of your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_changed': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2168,8 +2171,8 @@ your order for {event} has been changed.
|
||||
You can view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_paid': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2186,8 +2189,8 @@ we successfully received your payment for {event}. Thank you!
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_send_order_paid_attendee': {
|
||||
'type': bool,
|
||||
@@ -2206,8 +2209,8 @@ a ticket for {event} that has been ordered for you is now paid.
|
||||
You can view the details and status of your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_days_order_expire_warning': {
|
||||
'form_class': forms.IntegerField,
|
||||
@@ -2239,8 +2242,8 @@ your payment before {expire_date}.
|
||||
You can view the payment information and the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_pending_warning': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2256,8 +2259,8 @@ Please keep in mind that you are required to pay before {expire_date}.
|
||||
You can view the payment information and the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_incomplete_payment': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2276,8 +2279,8 @@ missing additional payment of **{pending_sum}**.
|
||||
You can view the payment information and the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_waiting_list': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2309,8 +2312,8 @@ as possible to the next person on the waiting list:
|
||||
|
||||
{url_remove}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_canceled': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2327,8 +2330,8 @@ your order {code} for {event} has been canceled.
|
||||
You can view the details of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_approved': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2347,8 +2350,8 @@ You can select a payment method and perform the payment here:
|
||||
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_send_order_approved_attendee': {
|
||||
'type': bool,
|
||||
@@ -2367,8 +2370,8 @@ we approved a ticket ordered for you for {event}.
|
||||
You can view the details and status of your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_approved_free': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2384,8 +2387,8 @@ at our event. As you only ordered free products, no payment is required.
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_send_order_approved_free_attendee': {
|
||||
'type': bool,
|
||||
@@ -2404,8 +2407,8 @@ we approved a ticket ordered for you for {event}.
|
||||
You can view the details and status of your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_order_denied': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2423,8 +2426,8 @@ You can view the details of your order here:
|
||||
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_text_order_custom_mail': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2433,8 +2436,8 @@ Your {event} team"""))
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_days_download_reminder': {
|
||||
'type': int,
|
||||
@@ -2452,13 +2455,13 @@ Your {event} team"""))
|
||||
'type': LazyI18nString,
|
||||
'default': LazyI18nString.from_gettext(gettext_noop("""Hello {attendee_name},
|
||||
|
||||
you are registered for {event}.
|
||||
you are registered for {event}.
|
||||
|
||||
If you did not do so already, you can download your ticket here:
|
||||
{url}
|
||||
If you did not do so already, you can download your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_download_reminder': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2473,8 +2476,8 @@ you bought a ticket for {event}.
|
||||
If you did not do so already, you can download your ticket here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
Best regards,
|
||||
Your {event} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_customer_registration': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2494,9 +2497,9 @@ This link is valid for one day.
|
||||
|
||||
If you did not sign up yourself, please ignore this email.
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
|
||||
Your {organizer} team"""))
|
||||
Your {organizer} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_customer_email_change': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2516,9 +2519,9 @@ This link is valid for one day.
|
||||
|
||||
If you did not request this, please ignore this email.
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
|
||||
Your {organizer} team"""))
|
||||
Your {organizer} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_customer_reset': {
|
||||
'type': LazyI18nString,
|
||||
@@ -2538,9 +2541,9 @@ This link is valid for one day.
|
||||
|
||||
If you did not request a new password, please ignore this email.
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
|
||||
Your {organizer} team"""))
|
||||
Your {organizer} team""")) # noqa: W291
|
||||
},
|
||||
'smtp_use_custom': {
|
||||
'default': 'False',
|
||||
@@ -3583,8 +3586,10 @@ class SettingsSandbox:
|
||||
def __delattr__(self, key: str) -> None:
|
||||
del self._event.settings[self._convert_key(key)]
|
||||
|
||||
def get(self, key: str, default: Any = None, as_type: type = str):
|
||||
return self._event.settings.get(self._convert_key(key), default=default, as_type=as_type)
|
||||
def get(self, key: str, default: Any = None, as_type: type = str, binary_file: bool = False):
|
||||
return self._event.settings.get(
|
||||
self._convert_key(key), default=default, as_type=as_type, binary_file=binary_file
|
||||
)
|
||||
|
||||
def set(self, key: str, value: Any):
|
||||
self._event.settings.set(self._convert_key(key), value)
|
||||
|
||||
@@ -175,6 +175,10 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
pre, pre code {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
{% if rtl %}
|
||||
body {
|
||||
direction: rtl;
|
||||
|
||||
@@ -91,12 +91,9 @@
|
||||
/* These are technically the same, but use both */
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
|
||||
-ms-word-break: break-all;
|
||||
/* This is the dangerous one in WebKit, as it breaks things wherever */
|
||||
word-break: break-all;
|
||||
/* Instead use this non-standard one: */
|
||||
word-break: break-word;
|
||||
|
||||
/* Adds a hyphen where the word breaks, if supported (No Blink) */
|
||||
-ms-hyphens: auto;
|
||||
@@ -105,6 +102,15 @@
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p a {
|
||||
word-wrap: anywhere;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
@@ -177,6 +183,7 @@
|
||||
}
|
||||
|
||||
.order {
|
||||
border-top: 1px solid #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -194,6 +201,10 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
pre, pre code {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
{% if rtl %}
|
||||
body {
|
||||
direction: rtl;
|
||||
|
||||
@@ -46,6 +46,8 @@ from django.urls import reverse
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.utils.safestring import mark_safe
|
||||
from markdown import Extension
|
||||
from markdown.inlinepatterns import SubstituteTagInlineProcessor
|
||||
from tlds import tld_set
|
||||
|
||||
register = template.Library()
|
||||
@@ -168,6 +170,21 @@ def abslink_callback(attrs, new=False):
|
||||
return attrs
|
||||
|
||||
|
||||
class EmailNl2BrExtension(Extension):
|
||||
"""
|
||||
In emails (mostly for backwards-compatibility), we do not follow GitHub Flavored Markdown in preserving newlines.
|
||||
Instead, we follow the CommonMark specification:
|
||||
|
||||
"A line ending (not in a code span or HTML tag) that is preceded by two or more spaces and does not occur at the
|
||||
end of a block is parsed as a hard line break (rendered in HTML as a <br /> tag)"
|
||||
"""
|
||||
BR_RE = r' \n'
|
||||
|
||||
def extendMarkdown(self, md):
|
||||
br_tag = SubstituteTagInlineProcessor(self.BR_RE, 'br')
|
||||
md.inlinePatterns.register(br_tag, 'nl', 5)
|
||||
|
||||
|
||||
def markdown_compile_email(source):
|
||||
linker = bleach.Linker(
|
||||
url_re=URL_RE,
|
||||
@@ -180,7 +197,7 @@ def markdown_compile_email(source):
|
||||
source,
|
||||
extensions=[
|
||||
'markdown.extensions.sane_lists',
|
||||
# 'markdown.extensions.nl2br' # disabled for backwards-compatibility
|
||||
EmailNl2BrExtension(),
|
||||
]
|
||||
),
|
||||
tags=ALLOWED_TAGS,
|
||||
|
||||
@@ -31,7 +31,8 @@ from django_scopes.forms import (
|
||||
)
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.models.checkin import CheckinList
|
||||
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
||||
from pretix.base.models.checkin import Checkin, CheckinList
|
||||
from pretix.control.forms import ItemMultipleChoiceField
|
||||
from pretix.control.forms.widgets import Select2
|
||||
|
||||
@@ -177,3 +178,26 @@ class SimpleCheckinListForm(forms.ModelForm):
|
||||
'subevent': SafeModelChoiceField,
|
||||
'gates': SafeModelMultipleChoiceField,
|
||||
}
|
||||
|
||||
|
||||
class CheckinListSimulatorForm(forms.Form):
|
||||
raw_barcode = forms.CharField(
|
||||
label=_("Barcode"),
|
||||
)
|
||||
datetime = forms.SplitDateTimeField(
|
||||
label=_("Check-in time"),
|
||||
widget=SplitDateTimePickerWidget(),
|
||||
)
|
||||
checkin_type = forms.ChoiceField(
|
||||
label=_("Check-in type"),
|
||||
choices=Checkin.CHECKIN_TYPES,
|
||||
)
|
||||
ignore_unpaid = forms.BooleanField(
|
||||
label=_("Allow check-in of unpaid order (if check-in list permits it)"),
|
||||
required=False,
|
||||
)
|
||||
questions_supported = forms.BooleanField(
|
||||
label=_("Support for check-in questions"),
|
||||
initial=True,
|
||||
required=False,
|
||||
)
|
||||
|
||||
@@ -1262,8 +1262,12 @@ class MailSettingsForm(SettingsForm):
|
||||
'mail_subject_order_placed_require_approval': ['event', 'order'],
|
||||
'mail_text_order_approved': ['event', 'order'],
|
||||
'mail_subject_order_approved': ['event', 'order'],
|
||||
'mail_text_order_approved_attendee': ['event', 'order'],
|
||||
'mail_subject_order_approved_attendee': ['event', 'order'],
|
||||
'mail_text_order_approved_free': ['event', 'order'],
|
||||
'mail_subject_order_approved_free': ['event', 'order'],
|
||||
'mail_text_order_approved_free_attendee': ['event', 'order'],
|
||||
'mail_subject_order_approved_free_attendee': ['event', 'order'],
|
||||
'mail_text_order_denied': ['event', 'order', 'comment'],
|
||||
'mail_subject_order_denied': ['event', 'order', 'comment'],
|
||||
'mail_text_order_paid': ['event', 'order', 'payment_info'],
|
||||
@@ -1396,7 +1400,7 @@ class CommentForm(I18nModelForm):
|
||||
fields = ['comment']
|
||||
widgets = {
|
||||
'comment': forms.Textarea(attrs={
|
||||
'rows': 3,
|
||||
'rows': 6,
|
||||
'class': 'helper-width-100',
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -573,6 +573,11 @@ class EventOrderExpertFilterForm(EventOrderFilterForm):
|
||||
label=_('Sales channel'),
|
||||
required=False,
|
||||
)
|
||||
has_checkin = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=FilterNullBooleanSelect,
|
||||
label=_('At least one ticket with check-in'),
|
||||
)
|
||||
checkin_attention = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=FilterNullBooleanSelect,
|
||||
@@ -745,6 +750,12 @@ class EventOrderExpertFilterForm(EventOrderFilterForm):
|
||||
qs = qs.filter(
|
||||
all_positions__country=fdata.get('attendee_address_country')
|
||||
).distinct()
|
||||
if fdata.get('has_checkin') is not None:
|
||||
qs = qs.annotate(
|
||||
has_checkin=Exists(
|
||||
Checkin.all.filter(position__order_id=OuterRef('pk'))
|
||||
)
|
||||
).filter(has_checkin=fdata['has_checkin'])
|
||||
if fdata.get('ticket_secret'):
|
||||
qs = qs.filter(
|
||||
all_positions__secret__icontains=fdata.get('ticket_secret')
|
||||
@@ -1743,9 +1754,9 @@ class CheckinListAttendeeFilterForm(FilterForm):
|
||||
label=_('Check-in status'),
|
||||
choices=(
|
||||
('', _('All attendees')),
|
||||
('3', pgettext_lazy('checkin state', 'Checked in but left')),
|
||||
('2', pgettext_lazy('checkin state', 'Present')),
|
||||
('1', _('Checked in')),
|
||||
('2', pgettext_lazy('checkin state', 'Present')),
|
||||
('3', pgettext_lazy('checkin state', 'Checked in but left')),
|
||||
('0', _('Not checked in')),
|
||||
),
|
||||
required=False,
|
||||
|
||||
@@ -895,7 +895,7 @@ class EventCancelForm(forms.Form):
|
||||
'Hello,\n\n'
|
||||
'with this email, we regret to inform you that {event} has been canceled.\n\n'
|
||||
'We will refund you {refund_amount} to your original payment method.\n\n'
|
||||
'You can view the current state of your order here:\n\n{url}\n\nBest regards,\n\n'
|
||||
'You can view the current state of your order here:\n\n{url}\n\nBest regards, \n\n'
|
||||
'Your {event} team'
|
||||
))
|
||||
)
|
||||
@@ -922,7 +922,7 @@ class EventCancelForm(forms.Form):
|
||||
'Hello,\n\n'
|
||||
'with this email, we regret to inform you that {event} has been canceled.\n\n'
|
||||
'You will therefore not receive a ticket from the waiting list.\n\n'
|
||||
'Best regards,\n\n'
|
||||
'Best regards, \n\n'
|
||||
'Your {event} team'
|
||||
))
|
||||
)
|
||||
|
||||
@@ -65,8 +65,8 @@ from pretix.base.forms.questions import (
|
||||
)
|
||||
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
||||
from pretix.base.models import (
|
||||
Customer, Device, EventMetaProperty, Gate, GiftCard, Membership,
|
||||
MembershipType, OrderPosition, Organizer, ReusableMedium, Team,
|
||||
Customer, Device, EventMetaProperty, Gate, GiftCard, GiftCardAcceptance,
|
||||
Membership, MembershipType, OrderPosition, Organizer, ReusableMedium, Team,
|
||||
)
|
||||
from pretix.base.models.customers import CustomerSSOClient, CustomerSSOProvider
|
||||
from pretix.base.models.organizer import OrganizerFooterLink
|
||||
@@ -637,7 +637,11 @@ class GiftCardCreateForm(forms.ModelForm):
|
||||
if GiftCard.objects.filter(
|
||||
secret__iexact=s
|
||||
).filter(
|
||||
Q(issuer=self.organizer) | Q(issuer__gift_card_collector_acceptance__collector=self.organizer)
|
||||
Q(issuer=self.organizer) |
|
||||
Q(issuer__in=GiftCardAcceptance.objects.filter(
|
||||
acceptor=self.organizer,
|
||||
active=True,
|
||||
).values_list('issuer', flat=True))
|
||||
).exists():
|
||||
raise ValidationError(
|
||||
_('A gift card with the same secret already exists in your or an affiliated organizer account.')
|
||||
@@ -790,6 +794,7 @@ class ReusableMediumCreateForm(ReusableMediumUpdateForm):
|
||||
|
||||
class CustomerUpdateForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'duplicate_identifier': _("An account with this customer ID is already registered."),
|
||||
'duplicate': _("An account with this email address is already registered."),
|
||||
}
|
||||
|
||||
@@ -824,6 +829,7 @@ class CustomerUpdateForm(forms.ModelForm):
|
||||
|
||||
def clean(self):
|
||||
email = self.cleaned_data.get('email')
|
||||
identifier = self.cleaned_data.get('identifier')
|
||||
|
||||
if email is not None:
|
||||
try:
|
||||
@@ -836,6 +842,17 @@ class CustomerUpdateForm(forms.ModelForm):
|
||||
code='duplicate',
|
||||
)
|
||||
|
||||
if identifier is not None:
|
||||
try:
|
||||
self.instance.organizer.customers.exclude(pk=self.instance.pk).get(identifier=identifier)
|
||||
except Customer.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['duplicate_identifier'],
|
||||
code='duplicate_identifier',
|
||||
)
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
@@ -1013,3 +1030,32 @@ class SSOClientForm(I18nModelForm):
|
||||
else:
|
||||
del self.fields['client_id']
|
||||
del self.fields['regenerate_client_secret']
|
||||
|
||||
|
||||
class GiftCardAcceptanceInviteForm(forms.Form):
|
||||
acceptor = forms.CharField(
|
||||
label=_("Organizer short name"),
|
||||
required=True,
|
||||
)
|
||||
reusable_media = forms.BooleanField(
|
||||
label=_("Allow access to reusable media"),
|
||||
help_text=_("This is required if you want the other organizer to participate in a shared system with e.g. "
|
||||
"NFC payment chips. You should only use this option for organizers you trust, since (depending "
|
||||
"on the activated medium types) this will grant the other organizer access to cryptographic key "
|
||||
"material required to interact with the media type."),
|
||||
required=False,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.organizer = kwargs.pop('organizer')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean_acceptor(self):
|
||||
val = self.cleaned_data['acceptor']
|
||||
try:
|
||||
acceptor = Organizer.objects.exclude(pk=self.organizer.pk).get(slug=val)
|
||||
except Organizer.DoesNotExist:
|
||||
raise ValidationError(_('The selected organizer does not exist or cannot be invited.'))
|
||||
if self.organizer.gift_card_acceptor_acceptance.filter(acceptor=acceptor).exists():
|
||||
raise ValidationError(_('The selected organizer has already been invited.'))
|
||||
return acceptor
|
||||
|
||||
@@ -271,7 +271,7 @@ class VoucherBulkForm(VoucherForm):
|
||||
required=False,
|
||||
initial=_('Hello,\n\n'
|
||||
'with this email, we\'re sending you one or more vouchers for {event}:\n\n{voucher_list}\n\n'
|
||||
'You can redeem them here in our ticket shop:\n\n{url}\n\nBest regards,\n\n'
|
||||
'You can redeem them here in our ticket shop:\n\n{url}\n\nBest regards, \n'
|
||||
'Your {event} team')
|
||||
)
|
||||
send_recipients = forms.CharField(
|
||||
|
||||
@@ -340,6 +340,9 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.organizer.export.schedule.failed': _('A scheduled export has failed: {reason}.'),
|
||||
'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'),
|
||||
'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'),
|
||||
'pretix.giftcards.acceptance.acceptor.invited': _('A new gift card acceptor has been invited.'),
|
||||
'pretix.giftcards.acceptance.issuer.removed': _('A gift card issuer has been removed or declined.'),
|
||||
'pretix.giftcards.acceptance.issuer.accepted': _('A new gift card issuer has been accepted.'),
|
||||
'pretix.webhook.created': _('The webhook has been created.'),
|
||||
'pretix.webhook.changed': _('The webhook has been changed.'),
|
||||
'pretix.webhook.retries.expedited': _('The webhook call retry jobs have been manually expedited.'),
|
||||
@@ -528,9 +531,10 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.permissions.invited': _('A user has been invited to the event team.'),
|
||||
'pretix.event.permissions.changed': _('A user\'s permissions have been changed.'),
|
||||
'pretix.event.permissions.deleted': _('A user has been removed from the event team.'),
|
||||
'pretix.waitinglist.voucher': _('A voucher has been sent to a person on the waiting list.'),
|
||||
'pretix.waitinglist.voucher': _('A voucher has been sent to a person on the waiting list.'), # legacy
|
||||
'pretix.event.orders.waitinglist.voucher_assigned': _('A voucher has been sent to a person on the waiting list.'),
|
||||
'pretix.event.orders.waitinglist.deleted': _('An entry has been removed from the waiting list.'),
|
||||
'pretix.event.orders.waitinglist.transferred': _('An entry has been transferred to another waiting list.'),
|
||||
'pretix.event.order.waitinglist.transferred': _('An entry has been transferred to another waiting list.'), # legacy
|
||||
'pretix.event.orders.waitinglist.changed': _('An entry has been changed on the waiting list.'),
|
||||
'pretix.event.orders.waitinglist.added': _('An entry has been added to the waiting list.'),
|
||||
'pretix.team.created': _('The team has been created.'),
|
||||
|
||||
@@ -519,13 +519,32 @@ def get_organizer_navigation(request):
|
||||
})
|
||||
|
||||
if 'can_manage_gift_cards' in request.orgapermset:
|
||||
children = []
|
||||
children.append({
|
||||
'label': _('Gift cards'),
|
||||
'url': reverse('control:organizer.giftcards', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.giftcard' in url.url_name and 'acceptance' not in url.url_name,
|
||||
'children': children,
|
||||
})
|
||||
if 'can_change_organizer_settings' in request.orgapermset:
|
||||
children.append(
|
||||
{
|
||||
'label': _('Acceptance'),
|
||||
'url': reverse('control:organizer.giftcards.acceptance', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.giftcards.acceptance' in url.url_name,
|
||||
}
|
||||
)
|
||||
nav.append({
|
||||
'label': _('Gift cards'),
|
||||
'url': reverse('control:organizer.giftcards', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.giftcard' in url.url_name,
|
||||
'icon': 'credit-card',
|
||||
'children': children,
|
||||
})
|
||||
|
||||
if request.organizer.settings.customer_accounts:
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
{% trans "Edit list configuration" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url "control:event.orders.export" event=request.event.slug organizer=request.event.organizer.slug %}?identifier=checkinlistpdf&checkinlistpdf-list={{ checkinlist.pk }}"
|
||||
<a href="{% url "control:event.orders.checkinlists.simulator" event=request.event.slug organizer=request.event.organizer.slug list=checkinlist.pk %}"
|
||||
class="btn btn-default">
|
||||
<span class="fa fa-flask"></span>
|
||||
{% trans "Check-in simulator" %}
|
||||
</a>
|
||||
<a href="{% url "control:event.orders.export" event=request.event.slug organizer=request.event.organizer.slug %}?identifier=checkinlistpdf&checkinlistpdf-list={{ checkinlist.pk }}{% if "status" in request.GET %}&checkinlistpdf-status={{ request.GET.status|urlencode }}{% endif %}"
|
||||
class="btn btn-default" target="_blank">
|
||||
<span class="fa fa-download"></span>
|
||||
{% trans "PDF" %}
|
||||
</a>
|
||||
<a href="{% url "control:event.orders.export" event=request.event.slug organizer=request.event.organizer.slug %}?identifier=checkinlist&checkinlist-list={{ checkinlist.pk }}"
|
||||
<a href="{% url "control:event.orders.export" event=request.event.slug organizer=request.event.organizer.slug %}?identifier=checkinlist&checkinlist-list={{ checkinlist.pk }}{% if "status" in request.GET %}&checkinlist-status={{ request.GET.status|urlencode }}{% endif %}"
|
||||
class="btn btn-default" target="_blank">
|
||||
<span class="fa fa-download"></span>
|
||||
{% trans "CSV" %}
|
||||
|
||||
@@ -12,7 +12,15 @@
|
||||
{% endblock %}
|
||||
{% block inside %}
|
||||
{% if checkinlist %}
|
||||
<h1>{% blocktrans with name=checkinlist.name %}Check-in list: {{ name }}{% endblocktrans %}</h1>
|
||||
<h1>
|
||||
{% blocktrans with name=checkinlist.name %}Check-in list: {{ name }}{% endblocktrans %}
|
||||
<a href="{% url "control:event.orders.checkinlists.simulator" event=request.event.slug organizer=request.event.organizer.slug list=checkinlist.pk %}"
|
||||
target="_blank"
|
||||
class="btn btn-default">
|
||||
<span class="fa fa-flask"></span>
|
||||
{% trans "Check-in simulator" %}
|
||||
</a>
|
||||
</h1>
|
||||
{% else %}
|
||||
<h1>{% trans "Check-in list" %}</h1>
|
||||
{% endif %}
|
||||
|
||||
@@ -133,6 +133,9 @@
|
||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||
<span class="fa fa-copy"></span>
|
||||
</a>
|
||||
<a href="{% url "control:event.orders.checkinlists.simulator" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||
title="{% trans "Check-in simulator" %}" data-toggle="tooltip"
|
||||
class="btn btn-default btn-sm"><i class="fa fa-flask"></i></a>
|
||||
<a href="{% url "control:event.orders.checkinlists.edit" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}" class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
||||
<a href="{% url "control:event.orders.checkinlists.delete" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
{% extends "pretixcontrol/items/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load escapejson %}
|
||||
{% load getitem %}
|
||||
{% load static %}
|
||||
{% load compress %}
|
||||
{% block title %}{% trans "Check-in simulator" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<h1>
|
||||
{% blocktrans with name=checkinlist.name %}Check-in list: {{ name }}{% endblocktrans %}
|
||||
{% if 'can_change_event_settings' in request.eventpermset %}
|
||||
<a href="{% url "control:event.orders.checkinlists.edit" event=request.event.slug organizer=request.event.organizer.slug list=checkinlist.pk %}"
|
||||
class="btn btn-default">
|
||||
<span class="fa fa-wrench"></span>
|
||||
{% trans "Edit list configuration" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</h1>
|
||||
<h2>{% trans "Check-in simulator" %}</h2>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
This tool allows you to validate your check-in configuration. You can enter a barcode plus some
|
||||
optional parameters and we will show you the response of the check-in list. No actual check-in will
|
||||
be performed and no modification to the system state is made.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_field form.raw_barcode layout="control" %}
|
||||
{% bootstrap_field form.datetime layout="control" %}
|
||||
{% bootstrap_field form.checkin_type layout="control" %}
|
||||
{% bootstrap_field form.ignore_unpaid layout="control" %}
|
||||
{% bootstrap_field form.questions_supported layout="control" %}
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Simulate" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% if result %}
|
||||
<hr>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-title">{% trans "Result" %}</div>
|
||||
</div>
|
||||
<div class="panel-body checkin-sim-result checkin-sim-result-status-{{ result.status }} checkin-sim-result-reason-{{ result.reason }}">
|
||||
{% if result.status == "ok" %}
|
||||
<span class="fa fa-check-circle"></span>
|
||||
{% elif result.status == "incomplete" %}
|
||||
<span class="fa fa-question-circle"></span>
|
||||
{% elif result.status == "error" %}
|
||||
{% if result.reason == "already_redeemed" %}
|
||||
<span class="fa fa-warning"></span>
|
||||
{% else %}
|
||||
<span class="fa fa-exclamation-circle"></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if result.status == "ok" %}
|
||||
<h3 class="nomargin-top">{% trans "Valid check-in" %}</h3>
|
||||
{% elif result.status == "incomplete" %}
|
||||
<h3 class="nomargin-top">{% trans "Additional information required" %}</h3>
|
||||
<p>
|
||||
{% trans "The following questions must be answered before check-in can be completed:" %}
|
||||
</p>
|
||||
<ul>
|
||||
{% for q in result.questions %}
|
||||
<li>
|
||||
<a href="{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}">
|
||||
{{ q.question }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% elif result.status == "error" %}
|
||||
<h3 class="nomargin-top">{{ reason_labels|getitem:result.reason }}</h3>
|
||||
{% if result.reason_explanation %}
|
||||
<p>{{ result.reason_explanation }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if result.position %}
|
||||
{% if result.position.require_attention %}
|
||||
<p>
|
||||
<span class="fa fa-info-circle fa-fw"></span> {% trans "Special attention required" %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
<span class="fa fa-ticket fa-fw"></span>
|
||||
<a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=result.position.order %}">
|
||||
{{ result.position.order }}</a>-{{ result.position.positionid }}
|
||||
</p>
|
||||
{% if result.position.attendee_name %}
|
||||
<p>
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
{{ result.position.attendee_name }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if result.rule_graph %}
|
||||
<div id="rules-editor" class="form-inline">
|
||||
<div role="tabpanel" class="tab-pane" id="rules-viz">
|
||||
<checkin-rules-visualization></checkin-rules-visualization>
|
||||
</div>
|
||||
<textarea id="id_rules" class="sr-only">{{ result.rule_graph|attr_escapejson_dumps }}</textarea>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if DEBUG %}
|
||||
<script type="text/javascript" src="{% static "vuejs/vue.js" %}"></script>
|
||||
{% else %}
|
||||
<script type="text/javascript" src="{% static "vuejs/vue.min.js" %}"></script>
|
||||
{% endif %}
|
||||
{% compress js %}
|
||||
<script type="text/javascript" src="{% static "d3/d3.v6.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-color.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-dispatch.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-ease.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-interpolate.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-selection.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-timer.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-transition.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-drag.v2.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "d3/d3-zoom.v2.js" %}"></script>
|
||||
{% endcompress %}
|
||||
{% compress js %}
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules/jsonlogic-boolalg.js" %}"></script>
|
||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/viz-node.vue' %}"></script>
|
||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/checkin-rules-visualization.vue' %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules.js" %}"></script>
|
||||
{% endcompress %}
|
||||
{% endblock %}
|
||||
@@ -8,7 +8,7 @@ If that was you, please enter the following confirmation code:
|
||||
|
||||
If this was not requested by you, you can safely ignore this email.
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
|
||||
Your {{ instance }} team
|
||||
{% endblocktrans %}
|
||||
@@ -4,6 +4,6 @@ you requested a new password. Please go to the following page to reset your pass
|
||||
|
||||
{{ url }}
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
Your pretix team
|
||||
{% endblocktrans %}
|
||||
@@ -11,7 +11,7 @@ If you want to join that team, just click on the following link:
|
||||
|
||||
If you do not want to join, you can safely ignore or delete this email.
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
|
||||
Your pretix team
|
||||
{% endblocktrans %}
|
||||
|
||||
@@ -11,6 +11,6 @@ You can review and change your account settings here:
|
||||
|
||||
{{ url }}
|
||||
|
||||
Best regards,
|
||||
Best regards,
|
||||
Your pretix team
|
||||
{% endblocktrans %}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
<a href="{% url "control:organizer.giftcard" organizer=gc.issuer.slug giftcard=gc.pk %}">
|
||||
{{ gc.secret }}
|
||||
</a>
|
||||
{% if gc.issuer != request.organizer %}
|
||||
<span class="text-muted">
|
||||
<br>
|
||||
<span class="fa fa-group"></span> {{ gc.issuer }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{% trans "Issuer" %}</dt>
|
||||
<dd>{{ gc.issuer }}</dd>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load urlreplace %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Invite organizer" %}
|
||||
</h1>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form layout="control" %}
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,150 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load urlreplace %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Gift cards acceptance" %}
|
||||
</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
This feature allows you to configure acceptance of gift cards across multiple organizer accounts.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<h2>
|
||||
{% trans "Other organizers you accept gift cards from" %}
|
||||
</h2>
|
||||
|
||||
{% if issuer_acceptance|length == 0 and not filter_form.filtered %}
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You are not accepting gift cards from other organizers yet. If you want to do so, the other
|
||||
organizer can add you to their list and afterwards, you can confirm this here.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% else %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Organizer" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Reusable media" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for gca in issuer_acceptance %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ gca.issuer.name }}<br><code>{{ gca.issuer.slug }}</code>
|
||||
</td>
|
||||
<td>
|
||||
{% if gca.active %}
|
||||
{% trans "active" %}
|
||||
{% else %}
|
||||
{% trans "invited" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if gca.reusable_media %}
|
||||
{% trans "active" %}
|
||||
{% else %}
|
||||
{% trans "disabled" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{% if gca.active %}
|
||||
<button class="btn btn-danger" name="delete_issuer" value="{{ gca.issuer.slug }}">
|
||||
{% trans "Remove" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-success" name="accept_issuer" value="{{ gca.issuer.slug }}">
|
||||
{% trans "Accept" %}
|
||||
</button>
|
||||
<button class="btn btn-danger" name="delete_issuer" value="{{ gca.issuer.slug }}">
|
||||
{% trans "Decline" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</form>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<h2>
|
||||
{% trans "Other organizers accepting gift cards from you" %}
|
||||
</h2>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You can invite other organizers to accept your gift cards. After you have done so, they need to go
|
||||
to the same page in their account and accept your invitation. Note that other organizers will be able
|
||||
to add money to gift cards as well that you will need to collect form them. It is your responsibility
|
||||
to handle the exchange of money to offset the transactions between the two organizers.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You can optionally control whether they can access your reusable media. This is required if you want
|
||||
them to participate in a shared system with e.g. NFC payment chips.
|
||||
{% endblocktrans %}
|
||||
{% blocktrans trimmed %}
|
||||
You should only use this option for organizers you trust, since (depending on the activated medium types)
|
||||
this will grant the other organizer access to cryptographic key material required to interact with
|
||||
the media type.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<a href="{% url "control:organizer.giftcards.acceptance.invite" organizer=request.organizer.slug %}" class="btn btn-default">
|
||||
{% trans "Invite new organizer" %}
|
||||
</a>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Organizer" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Reusable media" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for gca in acceptor_acceptance %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ gca.acceptor.name }}<br><code>{{ gca.acceptor.slug }}</code>
|
||||
</td>
|
||||
<td>
|
||||
{% if gca.active %}
|
||||
{% trans "active" %}
|
||||
{% else %}
|
||||
{% trans "invited" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if gca.reusable_media %}
|
||||
{% trans "active" %}
|
||||
{% else %}
|
||||
{% trans "disabled" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<button class="btn btn-danger" name="delete_acceptor" value="{{ gca.acceptor.slug }}">
|
||||
{% trans "Remove" %}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endblock %}
|
||||
@@ -99,44 +99,4 @@
|
||||
</div>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endif %}
|
||||
{% if not is_paginated or page_obj.number == 1 %}
|
||||
<form action="" method="post" class="form-inline">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Accepted gift cards of other organizers" %}</legend>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
If you have access to multiple organizer accounts, you can configure that ticket shops in
|
||||
this account will also accept gift codes issued through a different organizer account, and
|
||||
vice versa.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<ul>
|
||||
{% for gca in request.organizer.gift_card_issuer_acceptance.all %}
|
||||
<li>
|
||||
<strong>{{ gca.issuer }}</strong>
|
||||
<button type="submit" name="del" value="{{ gca.issuer.slug }}" class="btn btn-xs btn-danger">
|
||||
<span class="fa fa-trash"></span>
|
||||
</button>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>
|
||||
<em>{% trans "You are currently not accepting gift cards from other organizers." %}</em>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if other_organizers %}
|
||||
<li>
|
||||
<select name="add" class="form-control input-sm">
|
||||
<option></option>
|
||||
{% for o in other_organizers %}
|
||||
<option value="{{ o.slug }}">{{ o }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="btn btn-primary btn-sm" type="submit"><span class="fa fa-plus"></span></button>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -130,7 +130,10 @@
|
||||
</td>
|
||||
<td>
|
||||
<strong><a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}">
|
||||
{{ s.name }}</a></strong>
|
||||
{{ s.name }}</a></strong><br>
|
||||
<small class="text-muted">
|
||||
#{{ s.pk }}
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
{{ s.get_date_from_display }}<br>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
{% if redeemed_in_carts %}
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed with number=redeemed_in_carts %}
|
||||
This voucher is currently used in {{ number }} cart sessions and there might not be free to use until the cart sessions
|
||||
This voucher is currently used in {{ number }} cart sessions and might not be free to use until the cart sessions
|
||||
expire.
|
||||
{% endblocktrans %}
|
||||
<p class="text-right">
|
||||
|
||||
@@ -176,6 +176,10 @@ urlpatterns = [
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/$', organizer.GiftCardDetailView.as_view(), name='organizer.giftcard'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/edit$', organizer.GiftCardUpdateView.as_view(),
|
||||
name='organizer.giftcard.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcards/acceptance$', organizer.GiftCardAcceptanceListView.as_view(),
|
||||
name='organizer.giftcards.acceptance'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcards/acceptance/invite$', organizer.GiftCardAcceptanceInviteView.as_view(),
|
||||
name='organizer.giftcards.acceptance.invite'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhooks$', organizer.WebHookListView.as_view(), name='organizer.webhooks'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhook/add$', organizer.WebHookCreateView.as_view(),
|
||||
name='organizer.webhook.add'),
|
||||
@@ -429,6 +433,7 @@ urlpatterns = [
|
||||
re_path(r'^checkinlists/add$', checkin.CheckinListCreate.as_view(), name='event.orders.checkinlists.add'),
|
||||
re_path(r'^checkinlists/select2$', typeahead.checkinlist_select2, name='event.orders.checkinlists.select2'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/$', checkin.CheckInListShow.as_view(), name='event.orders.checkinlists.show'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/simulator$', checkin.CheckInListSimulator.as_view(), name='event.orders.checkinlists.simulator'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/bulk_action$', checkin.CheckInListBulkActionView.as_view(), name='event.orders.checkinlists.bulk_action'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/change$', checkin.CheckinListUpdate.as_view(),
|
||||
name='event.orders.checkinlists.edit'),
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# 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 <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
#
|
||||
# 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 <https://github.com/pretix/pretix>.
|
||||
#
|
||||
# This file contains Apache-licensed contributions copyrighted by: Jakob Schnell, jasonwaiting@live.hk, pajowu
|
||||
#
|
||||
# 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.
|
||||
import secrets
|
||||
from datetime import timezone
|
||||
|
||||
import dateutil.parser
|
||||
@@ -32,14 +45,21 @@ from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import is_aware, make_aware, now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import ListView
|
||||
from django.views.generic import FormView, ListView
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.api.views.checkin import _redeem_process
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.models import Checkin, Order, OrderPosition
|
||||
from pretix.base.models.checkin import CheckinList
|
||||
from pretix.base.services.checkin import (
|
||||
LazyRuleVars, _logic_annotate_for_graphic_explain,
|
||||
)
|
||||
from pretix.base.signals import checkin_created
|
||||
from pretix.base.views.tasks import AsyncPostView
|
||||
from pretix.control.forms.checkin import CheckinListForm
|
||||
from pretix.control.forms.checkin import (
|
||||
CheckinListForm, CheckinListSimulatorForm,
|
||||
)
|
||||
from pretix.control.forms.filter import (
|
||||
CheckinFilterForm, CheckinListAttendeeFilterForm,
|
||||
)
|
||||
@@ -48,18 +68,6 @@ from pretix.control.views import CreateView, PaginationMixin, UpdateView
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.models import modelcopy
|
||||
|
||||
# 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 <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
#
|
||||
# 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 <https://github.com/pretix/pretix>.
|
||||
#
|
||||
# This file contains Apache-licensed contributions copyrighted by: Jakob Schnell, jasonwaiting@live.hk, pajowu
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
class CheckInListQueryMixin:
|
||||
|
||||
@@ -469,3 +477,63 @@ class CheckinListView(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
ctx = super().get_context_data()
|
||||
ctx['filter_form'] = self.filter_form
|
||||
return ctx
|
||||
|
||||
|
||||
class CheckInListSimulator(EventPermissionRequiredMixin, FormView):
|
||||
template_name = 'pretixcontrol/checkin/simulator.html'
|
||||
permission = 'can_view_orders'
|
||||
form_class = CheckinListSimulatorForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
|
||||
self.result = None
|
||||
r = super().dispatch(request, *args, **kwargs)
|
||||
r['Content-Security-Policy'] = 'script-src \'unsafe-eval\''
|
||||
return r
|
||||
|
||||
def get_initial(self):
|
||||
return {
|
||||
'datetime': now()
|
||||
}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return super().get_context_data(
|
||||
**kwargs,
|
||||
checkinlist=self.list,
|
||||
result=self.result,
|
||||
reason_labels=dict(Checkin.REASONS),
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.result = _redeem_process(
|
||||
checkinlists=[self.list],
|
||||
raw_barcode=form.cleaned_data["raw_barcode"],
|
||||
answers_data={},
|
||||
datetime=form.cleaned_data["datetime"],
|
||||
force=False,
|
||||
checkin_type=form.cleaned_data["checkin_type"],
|
||||
ignore_unpaid=form.cleaned_data["ignore_unpaid"],
|
||||
untrusted_input=True,
|
||||
user=self.request.user,
|
||||
auth=None,
|
||||
expand=[],
|
||||
nonce=secrets.token_hex(12),
|
||||
pdf_data=False,
|
||||
questions_supported=form.cleaned_data["questions_supported"],
|
||||
canceled_supported=False,
|
||||
request=self.request, # this is not clean, but we need it in the serializers for URL generation
|
||||
legacy_url_support=False,
|
||||
simulate=True,
|
||||
).data
|
||||
|
||||
if form.cleaned_data["checkin_type"] == Checkin.TYPE_ENTRY and self.list.rules and self.result.get("position")\
|
||||
and (self.result["status"] in ("ok", "incomplete") or self.result["reason"] == "rules"):
|
||||
op = OrderPosition.objects.get(pk=self.result["position"]["id"])
|
||||
rule_data = LazyRuleVars(op, self.list, form.cleaned_data["datetime"])
|
||||
rule_graph = _logic_annotate_for_graphic_explain(self.list.rules, op.subevent or self.list.event, rule_data)
|
||||
self.result["rule_graph"] = rule_graph
|
||||
|
||||
if self.result.get("questions"):
|
||||
for q in self.result["questions"]:
|
||||
q["question"] = LazyI18nString(q["question"])
|
||||
return self.get(self.request, self.args, self.kwargs)
|
||||
|
||||
@@ -62,7 +62,7 @@ from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
from django.utils.translation import gettext, gettext_lazy as _, gettext_noop
|
||||
from django.views.generic import FormView, ListView
|
||||
from django.views.generic.base import TemplateView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
@@ -1511,12 +1511,12 @@ class QuickSetupView(FormView):
|
||||
event=self.request.event,
|
||||
initial=[
|
||||
{
|
||||
'name': LazyI18nString.from_gettext(gettext('Regular ticket')),
|
||||
'name': LazyI18nString.from_gettext(gettext_noop('Regular ticket')),
|
||||
'default_price': Decimal('35.00'),
|
||||
'quota': 100,
|
||||
},
|
||||
{
|
||||
'name': LazyI18nString.from_gettext(gettext('Reduced ticket')),
|
||||
'name': LazyI18nString.from_gettext(gettext_noop('Reduced ticket')),
|
||||
'default_price': Decimal('29.00'),
|
||||
'quota': 50,
|
||||
},
|
||||
|
||||
@@ -2261,8 +2261,13 @@ class ExportMixin:
|
||||
@cached_property
|
||||
def exporters(self):
|
||||
responses = register_data_exporters.send(self.request.event)
|
||||
raw_exporters = [response(self.request.event, self.request.organizer) for r, response in responses if response]
|
||||
raw_exporters = [
|
||||
ex for ex in raw_exporters
|
||||
if ex.available_for_user(self.request.user if self.request.user and self.request.user.is_authenticated else None)
|
||||
]
|
||||
return sorted(
|
||||
[response(self.request.event, self.request.organizer) for r, response in responses if response],
|
||||
raw_exporters,
|
||||
key=lambda ex: (0 if ex.category else 1, ex.category or "", 0 if ex.featured else 1, str(ex.verbose_name).lower())
|
||||
)
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ from pretix.base.models import (
|
||||
from pretix.base.models.customers import CustomerSSOClient, CustomerSSOProvider
|
||||
from pretix.base.models.event import Event, EventMetaProperty, EventMetaValue
|
||||
from pretix.base.models.giftcards import (
|
||||
GiftCardTransaction, gen_giftcard_secret,
|
||||
GiftCardAcceptance, GiftCardTransaction, gen_giftcard_secret,
|
||||
)
|
||||
from pretix.base.models.orders import CancellationRequest
|
||||
from pretix.base.models.organizer import TeamAPIToken
|
||||
@@ -96,12 +96,12 @@ from pretix.control.forms.filter import (
|
||||
from pretix.control.forms.orders import ExporterForm
|
||||
from pretix.control.forms.organizer import (
|
||||
CustomerCreateForm, CustomerUpdateForm, DeviceBulkEditForm, DeviceForm,
|
||||
EventMetaPropertyForm, GateForm, GiftCardCreateForm, GiftCardUpdateForm,
|
||||
MailSettingsForm, MembershipTypeForm, MembershipUpdateForm,
|
||||
OrganizerDeleteForm, OrganizerFooterLinkFormset, OrganizerForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, ReusableMediumCreateForm,
|
||||
ReusableMediumUpdateForm, SSOClientForm, SSOProviderForm, TeamForm,
|
||||
WebHookForm,
|
||||
EventMetaPropertyForm, GateForm, GiftCardAcceptanceInviteForm,
|
||||
GiftCardCreateForm, GiftCardUpdateForm, MailSettingsForm,
|
||||
MembershipTypeForm, MembershipUpdateForm, OrganizerDeleteForm,
|
||||
OrganizerFooterLinkFormset, OrganizerForm, OrganizerSettingsForm,
|
||||
OrganizerUpdateForm, ReusableMediumCreateForm, ReusableMediumUpdateForm,
|
||||
SSOClientForm, SSOProviderForm, TeamForm, WebHookForm,
|
||||
)
|
||||
from pretix.control.forms.rrule import RRuleForm
|
||||
from pretix.control.logdisplay import OVERVIEW_BANLIST
|
||||
@@ -181,7 +181,8 @@ class OrganizerDetail(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin
|
||||
return self.request.organizer
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.user.get_events_with_any_permission(self.request).select_related('organizer').prefetch_related(
|
||||
qs = self.request.user.get_events_with_any_permission(self.request).select_related(
|
||||
'organizer').prefetch_related(
|
||||
'organizer', '_settings_objects', 'organizer___settings_objects',
|
||||
'organizer__meta_properties',
|
||||
Prefetch(
|
||||
@@ -211,7 +212,8 @@ class OrganizerDetail(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['filter_form'] = self.filter_form
|
||||
ctx['meta_fields'] = [
|
||||
self.filter_form['meta_{}'.format(p.name)] for p in self.organizer.meta_properties.filter(filter_allowed=True)
|
||||
self.filter_form['meta_{}'.format(p.name)] for p in
|
||||
self.organizer.meta_properties.filter(filter_allowed=True)
|
||||
]
|
||||
return ctx
|
||||
|
||||
@@ -316,7 +318,8 @@ class MailSettingsPreview(OrganizerPermissionRequiredMixin, View):
|
||||
# get all supported placeholders with dummy values
|
||||
def placeholders(self, item):
|
||||
ctx = {}
|
||||
for p, s in MailSettingsForm(obj=self.request.organizer)._get_sample_context(MailSettingsForm.base_context[item]).items():
|
||||
for p, s in MailSettingsForm(obj=self.request.organizer)._get_sample_context(
|
||||
MailSettingsForm.base_context[item]).items():
|
||||
if s.strip().startswith('*'):
|
||||
ctx[p] = s
|
||||
else:
|
||||
@@ -341,7 +344,8 @@ class MailSettingsPreview(OrganizerPermissionRequiredMixin, View):
|
||||
if idx in self.supported_locale:
|
||||
with language(self.supported_locale[idx], self.request.organizer.settings.region):
|
||||
if k.startswith('mail_subject_'):
|
||||
msgs[self.supported_locale[idx]] = format_map(bleach.clean(v), self.placeholders(preview_item))
|
||||
msgs[self.supported_locale[idx]] = format_map(bleach.clean(v),
|
||||
self.placeholders(preview_item))
|
||||
else:
|
||||
msgs[self.supported_locale[idx]] = markdown_compile_email(
|
||||
format_map(v, self.placeholders(preview_item))
|
||||
@@ -395,7 +399,8 @@ class OrganizerDelete(AdministratorPermissionRequiredMixin, FormView):
|
||||
messages.success(self.request, _('The organizer has been deleted.'))
|
||||
return redirect(self.get_success_url())
|
||||
except ProtectedError as e:
|
||||
err = gettext('The organizer could not be deleted as some constraints (e.g. data created by plug-ins) do not allow it.')
|
||||
err = gettext(
|
||||
'The organizer could not be deleted as some constraints (e.g. data created by plug-ins) do not allow it.')
|
||||
|
||||
# Unlike deleting events (which is done by regular backend users), this feature can only be used by sysadmins,
|
||||
# so we expose more technical / less polished information.
|
||||
@@ -507,7 +512,8 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
|
||||
@cached_property
|
||||
def footer_links_formset(self):
|
||||
return OrganizerFooterLinkFormset(self.request.POST if self.request.method == "POST" else None, organizer=self.object,
|
||||
return OrganizerFooterLinkFormset(self.request.POST if self.request.method == "POST" else None,
|
||||
organizer=self.object,
|
||||
prefix="footer-links", instance=self.object)
|
||||
|
||||
def save_footer_links_formset(self, obj):
|
||||
@@ -664,7 +670,7 @@ class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
||||
def is_allowed(self) -> bool:
|
||||
return self.request.organizer.teams.exclude(pk=self.kwargs.get('team')).filter(
|
||||
can_change_teams=True, members__isnull=False
|
||||
).exists()
|
||||
).exists() or self.request.user.has_active_staff_session(self.request.session.session_key)
|
||||
|
||||
@transaction.atomic
|
||||
def delete(self, request, *args, **kwargs):
|
||||
@@ -748,7 +754,7 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
||||
else:
|
||||
other_admin_teams = self.request.organizer.teams.exclude(pk=self.object.pk).filter(
|
||||
can_change_teams=True, members__isnull=False
|
||||
).exists()
|
||||
).exists() or self.request.user.has_active_staff_session(self.request.session.session_key)
|
||||
if not other_admin_teams and self.object.can_change_teams and self.object.members.count() == 1:
|
||||
messages.error(self.request, _('You cannot remove the last member from this team as no one would '
|
||||
'be left with the permission to change teams.'))
|
||||
@@ -1328,6 +1334,95 @@ class WebHookLogsView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin
|
||||
}))
|
||||
|
||||
|
||||
class GiftCardAcceptanceInviteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView):
|
||||
model = GiftCardAcceptance
|
||||
template_name = 'pretixcontrol/organizers/giftcard_acceptance_invite.html'
|
||||
permission = 'can_change_organizer_settings'
|
||||
form_class = GiftCardAcceptanceInviteForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
return {
|
||||
**super().get_form_kwargs(),
|
||||
'organizer': self.request.organizer,
|
||||
}
|
||||
|
||||
def form_valid(self, form):
|
||||
self.request.organizer.gift_card_acceptor_acceptance.get_or_create(
|
||||
acceptor=form.cleaned_data['acceptor'],
|
||||
reusable_media=form.cleaned_data['reusable_media'],
|
||||
active=False,
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.invited',
|
||||
data={'acceptor': form.cleaned_data['acceptor'].slug,
|
||||
'reusable_media': form.cleaned_data['reusable_media']},
|
||||
user=self.request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected organizer has been invited.'))
|
||||
return redirect(
|
||||
reverse('control:organizer.giftcards.acceptance', kwargs={'organizer': self.request.organizer.slug}))
|
||||
|
||||
|
||||
class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||
model = GiftCardAcceptance
|
||||
template_name = 'pretixcontrol/organizers/giftcard_acceptance_list.html'
|
||||
permission = 'can_change_organizer_settings'
|
||||
context_object_name = 'acceptor_acceptance'
|
||||
paginate_by = 50
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.organizer.gift_card_acceptor_acceptance.select_related(
|
||||
'acceptor'
|
||||
).order_by('acceptor__name', 'acceptor_id')
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['issuer_acceptance'] = self.request.organizer.gift_card_issuer_acceptance.select_related(
|
||||
'issuer'
|
||||
)
|
||||
return ctx
|
||||
|
||||
@transaction.atomic()
|
||||
def post(self, request, *args, **kwargs):
|
||||
if "delete_acceptor" in request.POST:
|
||||
done = self.request.organizer.gift_card_acceptor_acceptance.filter(
|
||||
acceptor__slug=request.POST.get("delete_acceptor")
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.removed',
|
||||
data={'acceptor': request.POST.get("delete_acceptor")},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
elif "delete_issuer" in request.POST:
|
||||
done = self.request.organizer.gift_card_issuer_acceptance.filter(
|
||||
issuer__slug=request.POST.get("delete_issuer")
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.removed',
|
||||
data={'issuer': request.POST.get("delete_acceptor")},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
if "accept_issuer" in request.POST:
|
||||
done = self.request.organizer.gift_card_issuer_acceptance.filter(
|
||||
issuer__slug=request.POST.get("accept_issuer")
|
||||
).update(active=True)
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.accepted',
|
||||
data={'issuer': request.POST.get("accept_issuer")},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been accepted.'))
|
||||
|
||||
return redirect(
|
||||
reverse('control:organizer.giftcards.acceptance', kwargs={'organizer': self.request.organizer.slug}))
|
||||
|
||||
|
||||
class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||
model = GiftCard
|
||||
template_name = 'pretixcontrol/organizers/giftcards.html'
|
||||
@@ -1346,39 +1441,6 @@ class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
||||
qs = self.filter_form.filter_qs(qs)
|
||||
return qs
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if "add" in request.POST:
|
||||
o = self.request.user.get_organizers_with_permission(
|
||||
'can_manage_gift_cards', self.request
|
||||
).exclude(pk=self.request.organizer.pk).filter(
|
||||
slug=request.POST.get("add")
|
||||
).first()
|
||||
if o:
|
||||
self.request.organizer.gift_card_issuer_acceptance.get_or_create(
|
||||
issuer=o
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.added',
|
||||
data={'issuer': o.slug},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected gift card issuer has been added.'))
|
||||
if "del" in request.POST:
|
||||
o = Organizer.objects.filter(
|
||||
slug=request.POST.get("del")
|
||||
).first()
|
||||
if o:
|
||||
self.request.organizer.gift_card_issuer_acceptance.filter(
|
||||
issuer=o
|
||||
).delete()
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.removed',
|
||||
data={'issuer': o.slug},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected gift card issuer has been removed.'))
|
||||
return redirect(reverse('control:organizer.giftcards', kwargs={'organizer': self.request.organizer.slug}))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['filter_form'] = self.filter_form
|
||||
@@ -1621,7 +1683,8 @@ class ExportMixin:
|
||||
def exporters(self):
|
||||
responses = register_multievent_data_exporters.send(self.request.organizer)
|
||||
raw_exporters = [
|
||||
response(Event.objects.none() if issubclass(response, OrganizerLevelExportMixin) else self.events, self.request.organizer)
|
||||
response(Event.objects.none() if issubclass(response, OrganizerLevelExportMixin) else self.events,
|
||||
self.request.organizer)
|
||||
for r, response in responses
|
||||
if response
|
||||
]
|
||||
@@ -1629,12 +1692,14 @@ class ExportMixin:
|
||||
ex for ex in raw_exporters
|
||||
if (
|
||||
not isinstance(ex, OrganizerLevelExportMixin) or
|
||||
self.request.user.has_organizer_permission(self.request.organizer, ex.organizer_required_permission, self.request)
|
||||
)
|
||||
self.request.user.has_organizer_permission(self.request.organizer, ex.organizer_required_permission,
|
||||
self.request)
|
||||
) and ex.available_for_user(self.request.user if self.request.user and self.request.user.is_authenticated else None)
|
||||
]
|
||||
return sorted(
|
||||
raw_exporters,
|
||||
key=lambda ex: (0 if ex.category else 1, ex.category or "", 0 if ex.featured else 1, str(ex.verbose_name).lower())
|
||||
key=lambda ex: (
|
||||
0 if ex.category else 1, ex.category or "", 0 if ex.featured else 1, str(ex.verbose_name).lower())
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@@ -1691,7 +1756,8 @@ class ExportDoView(OrganizerPermissionRequiredMixin, ExportMixin, AsyncAction, T
|
||||
data = self.scheduled.export_form_data
|
||||
else:
|
||||
if not self.exporter.form.is_valid():
|
||||
messages.error(self.request, _('There was a problem processing your input. See below for error details.'))
|
||||
messages.error(self.request,
|
||||
_('There was a problem processing your input. See below for error details.'))
|
||||
return self.get(request, *args, **kwargs)
|
||||
data = self.exporter.form.cleaned_data
|
||||
|
||||
@@ -1764,7 +1830,8 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
else:
|
||||
initial = {}
|
||||
return RRuleForm(
|
||||
data=self.request.POST if self.request.method == 'POST' and self.request.POST.get("schedule") == "save" else None,
|
||||
data=self.request.POST if self.request.method == 'POST' and self.request.POST.get(
|
||||
"schedule") == "save" else None,
|
||||
prefix="rrule",
|
||||
initial=initial
|
||||
)
|
||||
@@ -1779,7 +1846,8 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
if not self.scheduled:
|
||||
initial = {
|
||||
"mail_subject": gettext("Export: {title}").format(title=self.exporter.verbose_name),
|
||||
"mail_template": gettext("Hello,\n\nattached to this email, you can find a new scheduled report for {name}.").format(
|
||||
"mail_template": gettext(
|
||||
"Hello,\n\nattached to this email, you can find a new scheduled report for {name}.").format(
|
||||
name=str(self.request.organizer.name)
|
||||
),
|
||||
"schedule_rrule_time": time(4, 0, 0),
|
||||
@@ -1787,7 +1855,8 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
else:
|
||||
initial = {}
|
||||
return ScheduledOrganizerExportForm(
|
||||
data=self.request.POST if self.request.method == 'POST' and self.request.POST.get("schedule") == "save" else None,
|
||||
data=self.request.POST if self.request.method == 'POST' and self.request.POST.get(
|
||||
"schedule") == "save" else None,
|
||||
prefix="schedule",
|
||||
instance=instance,
|
||||
initial=initial,
|
||||
@@ -1804,7 +1873,8 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
elif not self.exporter:
|
||||
for s in ctx['scheduled']:
|
||||
try:
|
||||
s.export_verbose_name = [e for e in self.exporters if e.identifier == s.export_identifier][0].verbose_name
|
||||
s.export_verbose_name = [e for e in self.exporters if e.identifier == s.export_identifier][
|
||||
0].verbose_name
|
||||
except IndexError:
|
||||
s.export_verbose_name = "?"
|
||||
return ctx
|
||||
@@ -2236,9 +2306,10 @@ class SSOProviderUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['redirect_uri'] = build_absolute_uri(self.request.organizer, 'presale:organizer.customer.login.return', kwargs={
|
||||
'provider': self.object.pk
|
||||
})
|
||||
ctx['redirect_uri'] = build_absolute_uri(self.request.organizer, 'presale:organizer.customer.login.return',
|
||||
kwargs={
|
||||
'provider': self.object.pk
|
||||
})
|
||||
return ctx
|
||||
|
||||
def get_form_kwargs(self):
|
||||
|
||||
@@ -148,10 +148,15 @@ class ShredDoView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixi
|
||||
return _('The selected data was deleted successfully.')
|
||||
|
||||
def get_error_url(self):
|
||||
return reverse('control:event.shredder.download', kwargs={
|
||||
if "file" in self.request.POST:
|
||||
return reverse('control:event.shredder.download', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'file': self.request.POST.get("file")
|
||||
})
|
||||
return reverse('control:event.shredder.start', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'file': self.request.POST.get("file")
|
||||
'organizer': self.request.event.organizer.slug
|
||||
})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
@@ -189,6 +189,11 @@ class WaitingListActionView(EventPermissionRequiredMixin, WaitingListQuerySetMix
|
||||
)
|
||||
wle.priority = self.request.event.waitinglistentries.aggregate(m=Max('priority'))['m'] + 1
|
||||
wle.save(update_fields=['priority'])
|
||||
wle.log_action(
|
||||
'pretix.event.orders.waitinglist.changed',
|
||||
data={'priority': wle.priority},
|
||||
user=self.request.user,
|
||||
)
|
||||
messages.success(request, _('The waiting list entry has been moved to the top.'))
|
||||
return self._redirect_back()
|
||||
except WaitingListEntry.DoesNotExist:
|
||||
@@ -202,6 +207,11 @@ class WaitingListActionView(EventPermissionRequiredMixin, WaitingListQuerySetMix
|
||||
)
|
||||
wle.priority = self.request.event.waitinglistentries.aggregate(m=Min('priority'))['m'] - 1
|
||||
wle.save(update_fields=['priority'])
|
||||
wle.log_action(
|
||||
'pretix.event.orders.waitinglist.changed',
|
||||
data={'priority': wle.priority},
|
||||
user=self.request.user,
|
||||
)
|
||||
messages.success(request, _('The waiting list entry has been moved to the end of the list.'))
|
||||
return self._redirect_back()
|
||||
except WaitingListEntry.DoesNotExist:
|
||||
@@ -391,7 +401,7 @@ class EntryTransfer(EventPermissionRequiredMixin, UpdateView):
|
||||
messages.success(self.request, _('The waitinglist entry has been transferred.'))
|
||||
if form.has_changed():
|
||||
self.object.log_action(
|
||||
'pretix.event.order.waitinglist.transferred', user=self.request.user, data={
|
||||
'pretix.event.orders.waitinglist.changed', user=self.request.user, data={
|
||||
k: form.cleaned_data.get(k) for k in form.changed_data
|
||||
}
|
||||
)
|
||||
|
||||
@@ -213,7 +213,7 @@ class Logic():
|
||||
|
||||
data = data or {}
|
||||
|
||||
operator = list(tests.keys())[0]
|
||||
operator = [k for k in tests.keys() if not k.startswith("__")][0]
|
||||
values = tests[operator]
|
||||
|
||||
# Easy syntax for unary operators, like {"var": "x"} instead of strict
|
||||
|
||||
@@ -25,6 +25,7 @@ import time
|
||||
from django.conf import settings
|
||||
from django.contrib.gis.geoip2 import GeoIP2
|
||||
from django.core.cache import cache
|
||||
from geoip2.errors import AddressNotFoundError
|
||||
|
||||
from pretix.helpers.http import get_client_ip
|
||||
|
||||
@@ -50,7 +51,10 @@ def _get_country(request):
|
||||
if not _geoip:
|
||||
_geoip = GeoIP2()
|
||||
|
||||
res = _geoip.country(get_client_ip(request))
|
||||
try:
|
||||
res = _geoip.country(get_client_ip(request))
|
||||
except AddressNotFoundError:
|
||||
return None
|
||||
return res['country_code']
|
||||
|
||||
|
||||
|
||||
+2426
-2102
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2021-09-15 11:22+0000\n"
|
||||
"Last-Translator: Mohamed Tawfiq <mtawfiq@wafyapp.com>\n"
|
||||
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -454,47 +454,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "جميع الشروط في الأسفل"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "خيار واحد على الأقل"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "بداية الفعالية"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "نهاية الفعالية"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "تسجيل الفعالية"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "تحديد التاريخ والوقت"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "الوقت المحدد"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "القدرة على التحمل (الدقائق)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "أضف شرطا"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "الدقائق"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -660,32 +660,32 @@ msgstr[3] "سيتم حجز العناصر لك في سلة التسوق لعدة
|
||||
msgstr[4] "سيتم حجز العناصر لك في سلة التسوق لدقائق {num}."
|
||||
msgstr[5] "سيتم حجز العناصر لك في سلة التسوق لمدة {num}."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "يحصل المنظم على %(currency) %(amount)"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "ستسترد %(currency)%(amount)"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "الرجاء إدخال المبلغ الذي يمكن للمنظم الاحتفاظ به."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "الرجاء إدخال عدد لأحد أنواع التذاكر."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "مطلوب"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "المنطقة الزمنية:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "التوقيت المحلي:"
|
||||
|
||||
|
||||
+2437
-2161
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2020-12-19 07:00+0000\n"
|
||||
"Last-Translator: albert <albert.serra.monner@gmail.com>\n"
|
||||
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -433,47 +433,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -629,34 +629,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "El contingut de la cistella ja no el teniu reservat."
|
||||
msgstr[1] "El contingut de la cistella ja no el teniu reservat."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "required"
|
||||
msgstr "Cistella expirada"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2464
-2132
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2023-03-19 06:00+0000\n"
|
||||
"Last-Translator: Michael <michael.happl@gmx.at>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -445,47 +445,47 @@ msgstr "Minuty od předchozího vstupu (-1 pro první vstup)"
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr "Minuty od prvního vstupu (-1 pro první vstup)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "Všechny následující podmínky (AND)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "Alespoň jedna z následujících podmínek (OR)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Začátek akce"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Konec akce"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Vstup na akci"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "Pevný termín"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "Pevná doba"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Tolerance (v minutách)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Přidat podmínku"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "minuty"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr "Duplikát"
|
||||
|
||||
@@ -647,32 +647,32 @@ msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
"Produkty v nákupním košíku jsou pro vás rezervovány na dalších {num} minut."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "Organizátor si ponechává %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Dostanete %(currency)s %(amount)s zpět"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Zadejte částku, kterou si organizátor může ponechat."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Zadejte prosím množství pro jeden z typů vstupenek."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "povinný"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Časové pásmo:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "Místní čas:"
|
||||
|
||||
|
||||
+2374
-2124
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2022-12-01 17:00+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -465,47 +465,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -668,40 +668,40 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Varerne i din kurv er reserveret for dig i et minut."
|
||||
msgstr[1] "Varerne i din kurv er reserveret for dig i {num} minutter."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "fra %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "fra %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "required"
|
||||
msgstr "Kurv udløbet"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Tidszone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "Din lokaltid:"
|
||||
|
||||
|
||||
+2453
-2140
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2023-02-09 13:56+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -448,47 +448,47 @@ msgstr "Minuten seit vorherigem Eintritt (-1 bei erstem Zutritt)"
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr "Minuten seit erstem Eintritt (-1 bei erstem Zutritt)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "Alle der folgenden Bedingungen (UND)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "Mindestens eine der folgenden Bedingungen (ODER)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Veranstaltungsbeginn"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Veranstaltungsende"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Einlass"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "Fester Zeitpunkt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "Feste Uhrzeit"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Toleranz (Minuten)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Bedingung hinzufügen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "Minuten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -651,32 +651,32 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Die Produkte in Ihrem Warenkorb sind noch {num} Minuten für Sie reserviert."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "Der Veranstalter behält %(currency)s %(amount)s ein"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Sie erhalten %(currency)s %(amount)s zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Bitte geben Sie den Betrag ein, den der Veranstalter einbehalten darf."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Bitte tragen Sie eine Menge für eines der Produkte ein."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "verpflichtend"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Zeitzone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "Deine lokale Zeit:"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2023-02-09 13:56+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
@@ -447,47 +447,47 @@ msgstr "Minuten seit vorherigem Zutritt (-1 beim erstem Zutritt)"
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr "Minuten seit erstem Zutritt (-1 bei erstem Zutritt)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "Alle der folgenden Bedingungen (UND)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "Mindestens eine der folgenden Bedingungen (ODER)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Veranstaltungsbeginn"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Veranstaltungsende"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Einlass"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "Fester Zeitpunkt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "Feste Uhrzeit"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Toleranz (Minuten)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Bedingung hinzufügen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "Minuten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -650,32 +650,32 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Die Produkte in deinem Warenkorb sind noch {num} Minuten für dich reserviert."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "Der Veranstalter behält %(currency)s %(amount)s ein"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Du erhältst %(currency)s %(amount)s zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Bitte gib den Betrag ein, den der Veranstalter einbehalten darf."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Bitte trage eine Menge für eines der Produkte ein."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "verpflichtend"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Zeitzone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "Deine lokale Zeit:"
|
||||
|
||||
|
||||
+2328
-2119
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -432,47 +432,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -624,32 +624,32 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2401
-2134
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2019-10-03 19:00+0000\n"
|
||||
"Last-Translator: Chris Spy <chrispiropoulou@hotmail.com>\n"
|
||||
"Language-Team: Greek <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -482,47 +482,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -690,40 +690,40 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Τα είδη στο καλάθι θα παραμείνουν δεσμευμένα για ένα λεπτό."
|
||||
msgstr[1] "Τα είδη στο καλάθι θα παραμείνουν δεσμευμένα για {num} λεπτά."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "απο %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "απο %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Εισαγάγετε μια ποσότητα για έναν από τους τύπους εισιτηρίων."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "required"
|
||||
msgstr "Το καλάθι έληξε"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2401
-2130
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2021-11-25 21:00+0000\n"
|
||||
"Last-Translator: Ismael Menéndez Fernández <ismael.menendez@balidea.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -451,47 +451,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "Todas las siguientes condiciones (Y)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "Al menos una de las siguientes condiciones (O)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Inicio del evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Fin del evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Admisión al evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "seleccionar fecha y hora"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "seleccionar hora"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Tolerancia (en minutos)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Añadir condición"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "minutos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -654,32 +654,32 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Los elementos en su carrito de compras se han reservado por {num} minutos."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "El organizador se queda %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Obtienes %(currency)s %(price)s de vuelta"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Por favor, ingrese el monto que el organizador puede quedarse."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Por favor, introduzca un valor para cada tipo de entrada."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "campo requerido"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Zona horaria:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "Su hora local:"
|
||||
|
||||
|
||||
+2394
-2110
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2021-11-10 05:00+0000\n"
|
||||
"Last-Translator: Jaakko Rinta-Filppula <jaakko@r-f.fi>\n"
|
||||
"Language-Team: Finnish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -453,49 +453,49 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Tapahtuma alkaa"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Tapahtuma päättyy"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
#, fuzzy
|
||||
#| msgid "Current date and time"
|
||||
msgid "custom date and time"
|
||||
msgstr "Nykyinen päivämäärä ja aika"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "mukautettu aika"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Toleranssi (minuuttia)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Lisää ehto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -653,34 +653,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Ostoskorissasi olevat tuotteet eivät ole enää varattu sinulle."
|
||||
msgstr[1] "Ostoskorissasi olevat tuotteet eivät ole enää varattu sinulle."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "required"
|
||||
msgstr "Ostoskori on vanhentunut"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Aikavyöhyke:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+6156
-5679
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: French\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"PO-Revision-Date: 2023-04-06 22:00+0000\n"
|
||||
"Last-Translator: Loïc Alejandro <loic.alejandro@e.email>\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2023-06-17 09:09+0000\n"
|
||||
"Last-Translator: Ronan LE MEILLAT <ronan.le_meillat@highcanfly.club>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"fr/>\n"
|
||||
"Language: fr\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.16.4\n"
|
||||
"X-Generator: Weblate 4.17\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -90,43 +90,43 @@ msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
|
||||
msgid "Verkkopankki"
|
||||
msgstr ""
|
||||
msgstr "Verkkopankki"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
|
||||
msgid "PayU"
|
||||
msgstr ""
|
||||
msgstr "PayU"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
|
||||
msgid "BLIK"
|
||||
msgstr ""
|
||||
msgstr "BLIK"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
|
||||
msgid "Trustly"
|
||||
msgstr ""
|
||||
msgstr "Trustly"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
|
||||
msgid "Zimpler"
|
||||
msgstr ""
|
||||
msgstr "Zimpler"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
|
||||
msgid "Maxima"
|
||||
msgstr ""
|
||||
msgstr "Maxima"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
|
||||
msgid "OXXO"
|
||||
msgstr ""
|
||||
msgstr "OXXO"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
|
||||
msgid "Boleto"
|
||||
msgstr ""
|
||||
msgstr "Boleto"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
|
||||
msgid "WeChat Pay"
|
||||
msgstr ""
|
||||
msgstr "WeChat Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
|
||||
msgid "Mercado Pago"
|
||||
msgstr ""
|
||||
msgstr "Mercado Pago"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:164
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
||||
@@ -175,24 +175,23 @@ msgstr "Sélectionner une liste d'enregistrement"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
||||
msgid "No active check-in lists found."
|
||||
msgstr ""
|
||||
msgstr "Aucune liste d'enregistrement active n'a été trouvée."
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
||||
msgid "Switch check-in list"
|
||||
msgstr ""
|
||||
msgstr "Changer de liste d'enregistrement"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
||||
msgid "Search results"
|
||||
msgstr "Résultats de recherche"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
||||
#, fuzzy
|
||||
msgid "No tickets found"
|
||||
msgstr "Fermer la billetterie"
|
||||
msgstr "Aucun billet trouvé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
||||
msgid "Result"
|
||||
msgstr ""
|
||||
msgstr "Résultat"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
||||
msgid "This ticket requires special attention"
|
||||
@@ -200,7 +199,7 @@ msgstr "Ce ticket nécessite une attention particulière"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
||||
msgid "Switch direction"
|
||||
msgstr ""
|
||||
msgstr "Changer la direction"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
||||
msgid "Entry"
|
||||
@@ -212,19 +211,19 @@ msgstr "Quitter"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
||||
msgid "Scan a ticket or search and press return…"
|
||||
msgstr ""
|
||||
msgstr "Scanner ou rechercher le ticket et confirmer avec Entrée…"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
msgstr "Charger plus"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
||||
msgid "Valid"
|
||||
msgstr ""
|
||||
msgstr "Valide"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
||||
msgid "Unpaid"
|
||||
msgstr ""
|
||||
msgstr "Non payé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
||||
@@ -232,9 +231,8 @@ msgid "Canceled"
|
||||
msgstr "Annulé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
||||
#, fuzzy
|
||||
msgid "Redeemed"
|
||||
msgstr "Echanger"
|
||||
msgstr "Échangé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
||||
msgid "Cancel"
|
||||
@@ -247,27 +245,27 @@ msgstr "Ticket non payé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||
msgstr ""
|
||||
msgstr "Ce billet n'a pas encore été payé. Continuer quand même ?"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
||||
msgid "Additional information required"
|
||||
msgstr ""
|
||||
msgstr "Plus d'informations requises"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
||||
msgid "Valid ticket"
|
||||
msgstr ""
|
||||
msgstr "Billet valide"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
||||
msgid "Exit recorded"
|
||||
msgstr ""
|
||||
msgstr "Sortie enregistrée"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
||||
msgid "Ticket already used"
|
||||
msgstr ""
|
||||
msgstr "Billet déjà utilisé"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
||||
msgid "Information required"
|
||||
msgstr ""
|
||||
msgstr "Informations nécessaires"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
||||
msgid "Unknown ticket"
|
||||
@@ -275,11 +273,11 @@ msgstr "Billet inconnu"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
||||
msgid "Ticket type not allowed here"
|
||||
msgstr ""
|
||||
msgstr "Type de billet non autorisé ici"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
||||
msgid "Entry not allowed"
|
||||
msgstr ""
|
||||
msgstr "Entrée non autorisée"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
||||
msgid "Ticket code revoked/changed"
|
||||
@@ -302,40 +300,36 @@ msgid "Ticket code is ambiguous on list"
|
||||
msgstr "Le code du billet est ambigu dans la liste"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
||||
#, fuzzy
|
||||
msgid "Checked-in Tickets"
|
||||
msgstr "Enregistrement QR code"
|
||||
msgstr "Billets enregistrés"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
||||
msgid "Valid Tickets"
|
||||
msgstr ""
|
||||
msgstr "Billets valides"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
||||
msgid "Currently inside"
|
||||
msgstr ""
|
||||
msgstr "Présent actuellement"
|
||||
|
||||
#: pretix/static/lightbox/js/lightbox.js:96
|
||||
#, fuzzy
|
||||
msgid "close"
|
||||
msgstr "Fermer"
|
||||
msgstr "fermer"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:43
|
||||
#: pretix/static/pretixbase/js/asynctask.js:120
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Your request is currently being processed. Depending on the size of your "
|
||||
"event, this might take up to a few minutes."
|
||||
msgstr ""
|
||||
"Votre demande a été mise en attente sur le serveur et sera traitée. Selon la "
|
||||
"taille de votre événement, cela peut prendre jusqu' à quelques minutes."
|
||||
"Votre demande est maintenant en cours de traitement. Selon la taille de "
|
||||
"votre événement, cela peut prendre jusqu' à quelques minutes."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:48
|
||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
||||
#, fuzzy
|
||||
msgid "Your request has been queued on the server and will soon be processed."
|
||||
msgstr ""
|
||||
"Votre demande a été mise en attente sur le serveur et sera traitée. Selon la "
|
||||
"taille de votre événement, cela peut prendre jusqu' à quelques minutes."
|
||||
"Votre demande a été mise en attente sur le serveur et sera traitée "
|
||||
"prochainement."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:54
|
||||
#: pretix/static/pretixbase/js/asynctask.js:131
|
||||
@@ -361,7 +355,7 @@ msgid ""
|
||||
"{code}"
|
||||
msgstr ""
|
||||
"Nous ne pouvons actuellement pas atteindre le serveur, mais nous continuons "
|
||||
"d'essayer. Dernier code d'erreur: {code}"
|
||||
"d'essayer. Dernier code d'erreur : {code}"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:145
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||
@@ -374,7 +368,7 @@ msgid ""
|
||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||
msgstr ""
|
||||
"Actuellement, nous ne pouvons pas atteindre le serveur. Veuillez réessayer. "
|
||||
"Code d'erreur: {code}"
|
||||
"Code d'erreur : {code}"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:215
|
||||
msgid "We are processing your request …"
|
||||
@@ -406,96 +400,95 @@ msgstr "Appuyez sur Ctrl-C pour copier !"
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:10
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:16
|
||||
msgid "is one of"
|
||||
msgstr ""
|
||||
msgstr "est l'un des"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:22
|
||||
msgid "is before"
|
||||
msgstr ""
|
||||
msgstr "est avant"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:26
|
||||
msgid "is after"
|
||||
msgstr ""
|
||||
msgstr "est après"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:59
|
||||
msgid "Product"
|
||||
msgstr "Produit"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:63
|
||||
#, fuzzy
|
||||
msgid "Product variation"
|
||||
msgstr "Voir les variations"
|
||||
msgstr "Variation du produit"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:67
|
||||
msgid "Current date and time"
|
||||
msgstr ""
|
||||
msgstr "Date et heure courante"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:71
|
||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||
msgstr ""
|
||||
msgstr "Jour courant de la semaine (1 = Lundi, 7 = Dimanche)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:75
|
||||
msgid "Number of previous entries"
|
||||
msgstr ""
|
||||
msgstr "Nombre d'entrées précédentes"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:79
|
||||
msgid "Number of previous entries since midnight"
|
||||
msgstr ""
|
||||
msgstr "Nombre d'entrées depuis minuit"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:83
|
||||
msgid "Number of days with a previous entry"
|
||||
msgstr ""
|
||||
msgstr "Nombre de jours avec entrée préalable"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:87
|
||||
msgid "Minutes since last entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minutes depuis la dernière entrée (-1 à la première entrée)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:91
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minutes depuis la première entrée (-1 à la première entrée)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
msgstr "Toutes les conditions suivantes (ET)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
msgstr "Au moins une des conditions suivantes (OU)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Début de l'événement"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Fin de l'événement"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Admission à l'événement"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "date et heure personnalisée"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "heure personnalisée"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Tolérance (minutes)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Ajouter une condition"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "minutes"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
msgstr "Doublon"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:72
|
||||
msgid "Check-in QR"
|
||||
@@ -520,9 +513,8 @@ msgid "Barcode area"
|
||||
msgstr "Zone de code-barres"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:657
|
||||
#, fuzzy
|
||||
msgid "Image area"
|
||||
msgstr "Zone de code-barres"
|
||||
msgstr "Zone d'image"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:659
|
||||
msgid "Powered by pretix"
|
||||
@@ -565,7 +557,7 @@ msgstr "Erreur inconnue."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Votre choix couleur a un bon contraste et il est très facile à lire!"
|
||||
msgstr "Votre choix couleur a un bon contraste et il est très facile à lire !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
@@ -583,7 +575,7 @@ msgstr ""
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
msgstr "Requête de recherche"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
@@ -595,7 +587,7 @@ msgstr "Aucun"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
msgstr "Seuls les sélectionnés"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
@@ -638,11 +630,12 @@ msgstr[0] "(une date en plus)"
|
||||
msgstr[1] "({num} plus de dates)"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:43
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The items in your cart are no longer reserved for you. You can still "
|
||||
"complete your order as long as they’re available."
|
||||
msgstr "Les articles de votre panier ne vous sont plus réservés."
|
||||
msgstr ""
|
||||
"Les articles de votre panier ne vous sont plus réservés. Vous pouvez "
|
||||
"toujours terminer votre commande tant qu’ils sont disponibles."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:45
|
||||
msgid "Cart expired"
|
||||
@@ -654,71 +647,66 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Les articles de votre panier sont réservés pour une minute."
|
||||
msgstr[1] "Les articles de votre panier sont réservés pendant {num} minutes."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#, fuzzy
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "de %(currency)s %(price)s"
|
||||
msgstr "L'organisateur retient %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#, fuzzy
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "de %(currency)s %(price)s"
|
||||
msgstr "Vous recevez en retour %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
msgstr "Veuillez indiquer le montant que l'organisateur est autorisé à retenir."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "SVP entrez une quantité pour un de vos types de billets."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#, fuzzy
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "Panier expiré"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
msgstr "obligatoire"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Fuseau horaire :"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
msgstr "Votre heure locale :"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
msgstr "Quantité"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Decrease quantity"
|
||||
msgstr ""
|
||||
msgstr "Diminuer la quantité"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
msgctxt "widget"
|
||||
msgid "Increase quantity"
|
||||
msgstr ""
|
||||
msgstr "Augmenter la quantité"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Prix"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
msgstr "Sélectionné %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Voir les variations"
|
||||
msgstr "Sélectionner les variations %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
@@ -774,7 +762,7 @@ msgstr "taxes en sus"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "actuellement disponible: %s"
|
||||
msgstr "actuellement disponible : %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
@@ -785,7 +773,7 @@ msgstr "Disponible avec un bon de réduction"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "quantité minimum à commander: %s"
|
||||
msgstr "quantité minimum à commander : %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
@@ -803,12 +791,14 @@ msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
"Il y a actuellement beaucoup d'utilisateurs dans cette boutique de billets. "
|
||||
"Veuillez ouvrir cette boutique de billets dans un nouvel onglet pour "
|
||||
"continuer."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
#, fuzzy
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Fermer la billetterie"
|
||||
msgstr "Ouvrir la billetterie"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
msgctxt "widget"
|
||||
@@ -821,6 +811,9 @@ msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
"Nous n'avons pas pu créer vore panier, car il y a actuellement trop "
|
||||
"d'utilisateurs dans cette boutique de billets. Veuillez cliquer sur "
|
||||
"\"Continuer\" pour réessayer dans un nouvel onglet."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
@@ -899,13 +892,12 @@ msgstr "Moins précédent"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr ""
|
||||
msgstr "La semaine prochaine"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#, fuzzy
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Moins précédent"
|
||||
msgstr "Semaine précédente"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
@@ -919,11 +911,14 @@ msgid ""
|
||||
"add yourself to the waiting list. We will then notify if seats are available "
|
||||
"again."
|
||||
msgstr ""
|
||||
"Certaines ou toutes les catégories de billets sont actuellement épuisées. Si "
|
||||
"vous le souhaitez, vous pouvez vous ajouter à la liste d’attente. Nous vous "
|
||||
"informerons alors si des places sont à nouveau disponibles."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
msgstr "Charger plus"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "Mo"
|
||||
|
||||
+2374
-2103
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2022-02-22 22:00+0000\n"
|
||||
"Last-Translator: Ismael Menéndez Fernández <ismael.menendez@balidea.com>\n"
|
||||
"Language-Team: Galician <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -451,47 +451,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "Todas as condicións seguintes (E)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "Polo menos unha das seguintes condicións (OU)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr "Comezo do evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr "Fin do evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr "Admisión ao evento"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr "Seleccionar data e hora"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr "Seleccionar hora"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr "Tolerancia (en minutos)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr "Engadir condición"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr "minutos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -651,32 +651,32 @@ msgstr[0] "Os artigos da túa cesta están reservados para ti durante un minuto.
|
||||
msgstr[1] ""
|
||||
"Os artigos da túa cesta están reservados para ti durante {num} minutos."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "O organizador queda %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Obtés %(currency)s %(price)s de volta"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Por favor, ingrese a cantidade que pode conservar o organizador."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Por favor, introduza un valor para cada tipo de entrada."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr "campo requirido"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr "Zona horaria:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr "A súa hora local:"
|
||||
|
||||
|
||||
+2328
-2119
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: 2021-09-24 13:54+0000\n"
|
||||
"Last-Translator: ofirtro <ofir.tro@gmail.com>\n"
|
||||
"Language-Team: Hebrew <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -440,47 +440,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -636,32 +636,32 @@ msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
msgstr[3] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2328
-2119
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-31 09:02+0000\n"
|
||||
"POT-Creation-Date: 2023-06-16 14:35+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -432,47 +432,47 @@ msgstr ""
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:113
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:114
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
msgid "Event start"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
msgid "Event end"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:116
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Event admission"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:117
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "custom date and time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:118
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:124
|
||||
msgid "custom time"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:125
|
||||
msgid "Tolerance (minutes)"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:120
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:126
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:121
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:128
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
@@ -624,32 +624,32 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:161
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:171
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:169
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:179
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:185
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:195
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:426
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:436
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:462
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:472
|
||||
msgid "required"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:565
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:584
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:594
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:575
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:585
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2354
-2103
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user