Compare commits

..

1 Commits

Author SHA1 Message Date
Raphael Michel
880e70af89 Add test coverage and small improvements to event cloning logic 2022-04-28 15:20:29 +02:00
239 changed files with 57885 additions and 83697 deletions

View File

@@ -31,7 +31,7 @@ RUN apt-get update && \
echo 'pretixuser ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers && \
mkdir /static && \
mkdir /etc/supervisord && \
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - && \
curl -fsSL https://deb.nodesource.com/setup_15.x | sudo -E bash - && \
apt-get install -y nodejs && \
curl -qL https://www.npmjs.com/install.sh | sh

View File

@@ -172,6 +172,8 @@ Cart position endpoints
* does not check or calculate prices but believes any prices you send
* does not support the redemption of vouchers
* does not prevent you from buying items that can only be bought with a voucher
* does not support file upload questions
@@ -189,7 +191,6 @@ Cart position endpoints
* ``expires`` (optional)
* ``includes_tax`` (optional, **deprecated**, do not use, will be removed)
* ``sales_channel`` (optional)
* ``voucher`` (optional, expect a voucher code)
* ``answers``
* ``question``

View File

@@ -34,7 +34,6 @@ allow_multiple_entries boolean If ``true``, su
allow_entry_after_exit boolean If ``true``, subsequent scans of a ticket on this list are valid if the last scan of the ticket was an exit scan.
rules object Custom check-in logic. The contents of this field are currently not considered a stable API and modifications through the API are highly discouraged.
exit_all_at datetime Automatically check out (i.e. perform an exit scan) at this point in time. After this happened, this property will automatically be set exactly one day into the future. Note that this field is considered "internal configuration" and if you pull the list with ``If-Modified-Since``, the daily change in this field will not trigger a response.
addon_match boolean If ``true``, tickets on this list can be redeemed by scanning their parent ticket if this still leads to an unambiguous match.
===================================== ========================== =======================================================
.. versionchanged:: 3.9
@@ -54,10 +53,6 @@ addon_match boolean If ``true``, ti
The ``ends_after`` and ``expand`` query parameters have been added.
.. versionchanged:: 4.12
The ``addon_match`` attribute has been added.
Endpoints
---------
@@ -99,7 +94,6 @@ Endpoints
"allow_entry_after_exit": true,
"exit_all_at": null,
"rules": {},
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
@@ -152,7 +146,6 @@ Endpoints
"allow_entry_after_exit": true,
"exit_all_at": null,
"rules": {},
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
@@ -252,7 +245,6 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
@@ -277,7 +269,6 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
@@ -332,7 +323,6 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
@@ -621,12 +611,8 @@ Order position endpoints
Tries to redeem an order position, identified by its internal ID, i.e. checks the attendee in. This endpoint
accepts a number of optional requests in the body.
**Tip:** Instead of an ID, you can also use the ``secret`` field as the lookup parameter. In this case, you should
always set ``untrusted_input=true`` as a query parameter to avoid security issues.
**Tip:** Instead of an ID, you can also use the ``secret`` field as the lookup parameter.
:query boolean untrusted_input: If set to true, the lookup parameter is **always** interpreted as a ``secret``, never
as an ``id``. This should be always set if you are passing through untrusted, scanned
data to avoid guessing of ticket IDs.
:<json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
you do not implement question handling in your user interface, you **must**
set this to ``false``. In that case, questions will just be ignored. Defaults
@@ -753,7 +739,6 @@ Order position endpoints
* ``already_redeemed`` - Ticket already has been redeemed
* ``product`` - Tickets with this product may not be scanned at this device
* ``rules`` - Check-in prevented by a user-defined rule
* ``ambiguous`` - Multiple tickets match scan, rejected
In case of reason ``rules``, there might be an additional response field ``reason_explanation`` with a human-readable
description of the violated rules. However, that field can also be missing or be ``null``.

View File

@@ -14,7 +14,6 @@ The customer resource contains the following public fields:
Field Type Description
===================================== ========================== =======================================================
identifier string Internal ID of the customer
external_identifier string External ID of the customer (or ``null``)
email string Customer email address
name string Name of this customer (or ``null``)
name_parts object of strings Decomposition of name (i.e. given name, family name)
@@ -25,7 +24,6 @@ last_login datetime Date and time o
date_joined datetime Date and time of registration
locale string Preferred language of the customer
last_modified datetime Date and time of modification of the record
notes string Internal notes and comments (or ``null``)
===================================== ========================== =======================================================
.. versionadded:: 4.0
@@ -60,7 +58,6 @@ Endpoints
"results": [
{
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"name": "John Doe",
"name_parts": {
@@ -72,8 +69,7 @@ Endpoints
"last_login": null,
"date_joined": "2021-04-06T13:44:22.809216Z",
"locale": "de",
"last_modified": "2021-04-06T13:44:22.809377Z",
"notes": null
"last_modified": "2021-04-06T13:44:22.809377Z"
}
]
}
@@ -107,7 +103,6 @@ Endpoints
{
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"name": "John Doe",
"name_parts": {
@@ -119,8 +114,7 @@ Endpoints
"last_login": null,
"date_joined": "2021-04-06T13:44:22.809216Z",
"locale": "de",
"last_modified": "2021-04-06T13:44:22.809377Z",
"notes": null
"last_modified": "2021-04-06T13:44:22.809377Z"
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -156,7 +150,6 @@ Endpoints
{
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
...
}
@@ -200,7 +193,6 @@ Endpoints
{
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
}
@@ -234,7 +226,6 @@ Endpoints
{
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": null,
}

View File

@@ -609,17 +609,13 @@ Fetching individual orders
Order ticket download
---------------------
.. versionchanged:: 4.10
The API now supports ticket downloads for pending orders if allowed by the event settings.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/download/(output)/
Download tickets for an order, identified by its order code. Depending on the chosen output, the response might
be a ZIP file, PDF file or something else. The order details response contains a list of output options for this
particular order.
Tickets can only be downloaded if ticket downloads are active and depending on event settings the order is either paid or pending. Note that in some cases the
Tickets can be only downloaded if the order is paid and if ticket downloads are active. Note that in some cases the
ticket file might not yet have been created. In that case, you will receive a status code :http:statuscode:`409` and
you are expected to retry the request after a short period of waiting.
@@ -1639,10 +1635,6 @@ Fetching individual positions
Order position ticket download
------------------------------
.. versionchanged:: 4.10
The API now supports ticket downloads for pending orders if allowed by the event settings.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/download/(output)/
Download tickets for one order position, identified by its internal ID.
@@ -1654,7 +1646,7 @@ Order position ticket download
The referenced URL can provide a download or a regular, human-viewable website - so it is advised to open this URL
in a webbrowser and leave it up to the user to handle the result.
Tickets can only be downloaded if ticket downloads are active and depending on event settings the order is either paid or pending. Also, depending on event
Tickets can be only downloaded if the order is paid and if ticket downloads are active. Also, depending on event
configuration downloads might be only unavailable for add-on products or non-admission products.
Note that in some cases the ticket file might not yet have been created. In that case, you will receive a status
code :http:statuscode:`409` and you are expected to retry the request after a short period of waiting.

View File

@@ -474,7 +474,6 @@ Endpoints
: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 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
:param event: The ``slug`` field of the event to fetch
:statuscode 200: no error

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View File

@@ -2,25 +2,8 @@
partition "data-based check" {
"Check based on local database" -down-> "Is addon_match set to true?"
"Check based on local database" --> "Is the order in status PAID or PENDING\nand is the position not canceled?"
--> if "" then
-down->[no] "Is the order in status PAID or PENDING\nand is the position not canceled?"
else
-right->[yes] "Build a list that includes the position\nas well as all its add-ons"
-down-> "Filter list for products that are part of the check-in list"
--> if "" then
-down->[one found] Proceed with the matching position
--> "Is the order in status PAID or PENDING\nand is the position not canceled?"
else
--> if "" then
-right->[none found] "Return error PRODUCT "
else
-down->[multiple found] Return error AMBIGUOUS
endif
endif
endif
"Is the order in status PAID or PENDING\nand is the position not canceled?" --> if "" then
-right->[no] "Return error CANCELED"
else
-down->[yes] "Is the product part of the check-in list?"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

After

Width:  |  Height:  |  Size: 147 KiB

View File

@@ -19,25 +19,8 @@ else
endif
===CHECK=== -down-> "Is addon_match set to true?"
===CHECK=== -down-> "Is the order in status PAID or PENDING\nand is the position not canceled?"
--> if "" then
-down->[no] "Is the order in status PAID or PENDING\nand is the position not canceled?"
else
-right->[yes] "Build a list that includes the position\nas well as all its add-ons"
-down-> "Filter list for products that are part of the check-in list"
--> if "" then
-down->[one found] Proceed with the matching position
--> "Is the order in status PAID or PENDING\nand is the position not canceled?"
else
--> if "" then
-right->[none found] "Return error PRODUCT "
else
-down->[multiple found] Return error AMBIGUOUS
endif
endif
endif
"Is the order in status PAID or PENDING\nand is the position not canceled?" --> if "" then
-right->[no] "Return error CANCELED"
else
-down->[yes] "Is the product part of the check-in list?"

View File

@@ -227,108 +227,6 @@ Endpoints
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer or event or exhibitor does not exist **or** you have no permission to view it.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/
Returns a list of all vouchers connected to an exhibitor. The response contains the same data as described in
:ref:`rest-vouchers`.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/vouchers/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"code": "43K6LKM37FBVR2YG",
"max_usages": 1,
"redeemed": 0,
"valid_until": null,
"block_quota": false,
"allow_ignore_quota": false,
"price_mode": "set",
"value": "12.00",
"item": 1,
"variation": null,
"quota": null,
"tag": "testvoucher",
"comment": "",
"seat": null,
"subevent": null
}
]
}
:query page: The page number in case of a multi-page result set, default is 1
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of the event to fetch
:param id: The ``id`` field of the exhibitor to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer or event or exhibitor does not exist **or** you have no permission to view it.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/attach/
Attaches an **existing** voucher to an exhibitor. You need to send either the ``id`` **or** the ``code`` field of
the voucher.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/vouchers/attach/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
{
"id": 15
}
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/vouchers/attach/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
{
"code": "43K6LKM37FBVR2YG"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{}
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of the event to use
:param id: The ``id`` field of the exhibitor to use
:statuscode 200: no error
:statuscode 400: Invalid data sent, e.g. voucher does not exist
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer or event or exhibitor does not exist **or** you have no permission to view it.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/
Create a new exhibitor.

View File

@@ -19,7 +19,6 @@ If you want to **create** a plugin, please go to the
certificates
digital
exhibitors
shipping
imported_secrets
webinar
presale-saml

View File

@@ -1,235 +0,0 @@
Shipping
========
The shipping plugin provides a HTTP API that exposes the various layouts used to generate PDF badges.
Shipping address resource
-------------------------
The shipping address resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
company string Customer company name
name string Customer name
street string Customer street
zipcode string Customer ZIP code
city string Customer city
country string Customer country code
state string Customer state (ISO 3166-2 code). Only supported in
AU, BR, CA, CN, MY, MX, and US.
gift boolean Request by customer to not disclose prices in the shipping
===================================== ========================== =======================================================
Shipping status resource
------------------------
The shipping status resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
method integer Internal ID of shipping method
status string Status, one of ``"new"`` or ``"shipped"``
method_type string Method type, one of ``"ship"``, ``"online"``, or ``"collect"``
===================================== ========================== =======================================================
Print job resource
------------------
The print job resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
code string Order code of the ticket order
event string Event slug
status string Status, one of ``"new"`` or ``"shipped"``
method string Method type, one of ``"ship"``, ``"online"``, or ``"collect"``
===================================== ========================== =======================================================
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/shippingaddress/
Returns the shipping address of an order
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/democon/orders/ABC12/shippingaddress/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"company": "ACME Corp",
"name": "John Doe",
"street": "Sesame Street 12\nAp. 5",
"zipcode": "12345",
"city": "Berlin",
"country": "DE",
"state": "",
"gift": false
}
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:param order: The ``code`` field of a valid order
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
:statuscode 404: The order does not exist or no shipping address is attached.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/shippingaddress/
Returns the shipping status of an order
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/democon/orders/ABC12/shippingstatus/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"method": 23,
"method_type": "ship",
"status": "new"
}
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:param order: The ``code`` field of a valid order
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
:statuscode 404: The order does not exist or no shipping address is attached.
.. http:get:: /api/v1/organizers/(organizer)/printjobs/
Returns a list of ticket orders, only useful with some query filters
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/printjobs/?method=ship&status=new HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"event": "democon",
"order": "ABC12",
"method": "ship",
"status": "new"
}
]
}
:query string method: Filter by response field ``method`` (can be passed multiple times)
:query string status: Filter by response field ``status``
:query string event: Filter by response field ``event``
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
.. http:get:: /api/v1/organizers/(organizer)/printjobs/poll/
Returns the PDF file for the next job to print.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/printjobs/poll/?method=ship&status=new HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/pdf
X-Pretix-Order-Code: ABC12
...
:query string method: Filter by response field ``method`` (can be passed multiple times)
:query string status: Filter by response field ``status``
:query string event: Filter by response field ``event``
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
.. http:post:: /api/v1/organizers/(organizer)/printjobs/(order)/ack/
Change an order's status to "shipped".
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/printjobs/ABC12/ack/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:param order: The ``code`` field of a valid order
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
:statuscode 404: The order does not exist.

View File

@@ -78,7 +78,7 @@ Synchronization setting any
----------------------------------------------- ----------------------------------- ----------------------------------------------------------------------- -----------------------------------------------------------------------
Ticket secrets any Random Signed Random Signed
=============================================== =================================== =================================== =================================== ================================= =====================================
Scenario supported on platforms Android, Desktop, iOS Android, Desktop, iOS Android, Desktop Android, Desktop, iOS Android, Desktop, iOS
Scenario supported on platforms Android, Desktop, iOS Android, Desktop, iOS Android, Desktop Android, Desktop Android, Desktop
Synchronization speed for large data sets slow slow fast fast
Tickets can be scanned yes yes yes no yes
Ticket is valid after sale immediately next sync (~5 minutes) immediately never immediately
@@ -90,7 +90,6 @@ Name and seat visible on scanner yes
Order-specific check-in attention flag yes yes yes (except directly after sale) n/a no
Ticket search by order code or name yes yes yes (except directly after sale) no no
Check-in statistics on scanner yes yes mostly accurate no no
Support for add-on check-in with main ticket yes yes yes (except directly after sale) no no
=============================================== =================================== =================================== =================================== ================================= =====================================
.. _EdDSA: https://en.wikipedia.org/wiki/EdDSA#Ed25519

View File

@@ -135,10 +135,6 @@ Alternatively, you can select one or more categories to be shown::
<pretix-widget event="https://pretix.eu/demo/democon/" categories="12,25"></pretix-widget>
Or variation IDs::
<pretix-widget event="https://pretix.eu/demo/democon/" variations="15,2,68"></pretix-widget>
Multi-event selection
---------------------

View File

@@ -14,8 +14,6 @@ recursive-include pretix/plugins/manualpayment/templates *
recursive-include pretix/plugins/manualpayment/static *
recursive-include pretix/plugins/paypal/templates *
recursive-include pretix/plugins/paypal/static *
recursive-include pretix/plugins/paypal2/templates *
recursive-include pretix/plugins/paypal2/static *
recursive-include pretix/plugins/pretixdroid/templates *
recursive-include pretix/plugins/pretixdroid/static *
recursive-include pretix/plugins/sendmail/templates *

View File

@@ -19,4 +19,4 @@
# 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/>.
#
__version__ = "4.12.0.dev0"
__version__ = "4.10.0.dev0"

View File

@@ -45,7 +45,6 @@ class PretixScanSecurityProfile(AllowListSecurityProfile):
allowlist = (
('GET', 'api-v1:version'),
('GET', 'api-v1:device.eventselection'),
('GET', 'api-v1:idempotency.query'),
('POST', 'api-v1:device.update'),
('POST', 'api-v1:device.revoke'),
('POST', 'api-v1:device.roll'),
@@ -77,7 +76,6 @@ class PretixScanNoSyncNoSearchSecurityProfile(AllowListSecurityProfile):
allowlist = (
('GET', 'api-v1:version'),
('GET', 'api-v1:device.eventselection'),
('GET', 'api-v1:idempotency.query'),
('POST', 'api-v1:device.update'),
('POST', 'api-v1:device.revoke'),
('POST', 'api-v1:device.roll'),
@@ -107,7 +105,6 @@ class PretixScanNoSyncSecurityProfile(AllowListSecurityProfile):
allowlist = (
('GET', 'api-v1:version'),
('GET', 'api-v1:device.eventselection'),
('GET', 'api-v1:idempotency.query'),
('POST', 'api-v1:device.update'),
('POST', 'api-v1:device.revoke'),
('POST', 'api-v1:device.roll'),
@@ -138,7 +135,6 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
allowlist = (
('GET', 'api-v1:version'),
('GET', 'api-v1:device.eventselection'),
('GET', 'api-v1:idempotency.query'),
('POST', 'api-v1:device.update'),
('POST', 'api-v1:device.revoke'),
('POST', 'api-v1:device.roll'),
@@ -155,8 +151,6 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
('GET', 'api-v1:ticketlayoutitem-list'),
('GET', 'api-v1:badgelayout-list'),
('GET', 'api-v1:badgeitem-list'),
('GET', 'api-v1:voucher-list'),
('GET', 'api-v1:voucher-detail'),
('GET', 'api-v1:order-list'),
('POST', 'api-v1:order-list'),
('GET', 'api-v1:order-detail'),

View File

@@ -23,7 +23,6 @@ import os
from datetime import timedelta
from django.core.files import File
from django.db.models import Q
from django.utils.crypto import get_random_string
from django.utils.timezone import now
from django.utils.translation import gettext_lazy
@@ -34,7 +33,7 @@ from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.order import (
AnswerCreateSerializer, AnswerSerializer, InlineSeatSerializer,
)
from pretix.base.models import Quota, Seat, Voucher
from pretix.base.models import Quota, Seat
from pretix.base.models.orders import CartPosition
@@ -62,12 +61,11 @@ class CartPositionCreateSerializer(I18nAwareModelSerializer):
seat = serializers.CharField(required=False, allow_null=True)
sales_channel = serializers.CharField(required=False, default='sales_channel')
includes_tax = serializers.BooleanField(required=False, allow_null=True)
voucher = serializers.CharField(required=False, allow_null=True)
class Meta:
model = CartPosition
fields = ('cart_id', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
'subevent', 'expires', 'includes_tax', 'answers', 'seat', 'sales_channel', 'voucher')
'subevent', 'expires', 'includes_tax', 'answers', 'seat', 'sales_channel')
def create(self, validated_data):
answers_data = validated_data.pop('answers')
@@ -127,46 +125,14 @@ class CartPositionCreateSerializer(I18nAwareModelSerializer):
raise ValidationError('The specified seat ID is not unique.')
else:
validated_data['seat'] = seat
if not seat.is_available(
sales_channel=validated_data.get('sales_channel', 'web'),
distance_ignore_cart_id=validated_data['cart_id'],
):
raise ValidationError(gettext_lazy('The selected seat "{seat}" is not available.').format(seat=seat.name))
elif seated:
raise ValidationError('The specified product requires to choose a seat.')
if validated_data.get('voucher'):
try:
voucher = self.context['event'].vouchers.get(code__iexact=validated_data.get('voucher'))
except Voucher.DoesNotExist:
raise ValidationError('The specified voucher does not exist.')
if voucher and not voucher.applies_to(validated_data.get('item'), validated_data.get('variation')):
raise ValidationError('The specified voucher is not valid for the given item and variation.')
if voucher and voucher.seat and voucher.seat != validated_data.get('seat'):
raise ValidationError('The specified voucher is not valid for this seat.')
if voucher and voucher.subevent_id and (not validated_data.get('subevent') or voucher.subevent_id != validated_data['subevent'].pk):
raise ValidationError('The specified voucher is not valid for this subevent.')
if voucher.valid_until is not None and voucher.valid_until < now():
raise ValidationError('The specified voucher is expired.')
redeemed_in_carts = CartPosition.objects.filter(
Q(voucher=voucher) & Q(event=self.context['event']) & Q(expires__gte=now())
)
cart_count = redeemed_in_carts.count()
v_avail = voucher.max_usages - voucher.redeemed - cart_count
if v_avail < 1:
raise ValidationError('The specified voucher has already been used the maximum number of times.')
validated_data['voucher'] = voucher
if validated_data.get('seat'):
if not validated_data['seat'].is_available(
sales_channel=validated_data.get('sales_channel', 'web'),
distance_ignore_cart_id=validated_data['cart_id'],
ignore_voucher_id=validated_data['voucher'].pk if validated_data.get('voucher') else None,
):
raise ValidationError(
gettext_lazy('The selected seat "{seat}" is not available.').format(seat=validated_data['seat'].name))
validated_data.pop('sales_channel')
# todo: does this make sense?
validated_data['custom_price_input'] = validated_data['price']

View File

@@ -37,7 +37,7 @@ class CheckinListSerializer(I18nAwareModelSerializer):
model = CheckinList
fields = ('id', 'name', 'all_products', 'limit_products', 'subevent', 'checkin_count', 'position_count',
'include_pending', 'auto_checkin_sales_channels', 'allow_multiple_entries', 'allow_entry_after_exit',
'rules', 'exit_all_at', 'addon_match')
'rules', 'exit_all_at')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@@ -977,18 +977,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
else:
ia = None
lock_required = False
for pos_data in positions_data:
pos_data['_quotas'] = list(
pos_data.get('variation').quotas.filter(subevent=pos_data.get('subevent'))
if pos_data.get('variation')
else pos_data.get('item').quotas.filter(subevent=pos_data.get('subevent'))
)
if pos_data.get('voucher') or pos_data.get('seat') or any(q.size is not None for q in pos_data['_quotas']):
lock_required = True
lockfn = self.context['event'].lock
if simulate or not lock_required:
if simulate:
lockfn = NoLockManager
with lockfn() as now_dt:
free_seats = set()
@@ -1112,7 +1102,9 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
str(pos_data.get('item'))
)]
new_quotas = pos_data['_quotas']
new_quotas = (pos_data.get('variation').quotas.filter(subevent=pos_data.get('subevent'))
if pos_data.get('variation')
else pos_data.get('item').quotas.filter(subevent=pos_data.get('subevent')))
if len(new_quotas) == 0:
errs[i]['item'] = [gettext_lazy('The product "{}" is not assigned to a quota.').format(
str(pos_data.get('item'))
@@ -1166,7 +1158,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
pos_data['attendee_name_parts'] = {
'_legacy': attendee_name
}
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k != 'answers' and k != '_quotas'})
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k != 'answers'})
if simulate:
pos.order = order._wrapped
else:

View File

@@ -71,8 +71,8 @@ class CustomerSerializer(I18nAwareModelSerializer):
class Meta:
model = Customer
fields = ('identifier', 'external_identifier', 'email', 'name', 'name_parts', 'is_active', 'is_verified', 'last_login', 'date_joined',
'locale', 'last_modified', 'notes')
fields = ('identifier', 'email', 'name', 'name_parts', 'is_active', 'is_verified', 'last_login', 'date_joined',
'locale', 'last_modified')
class MembershipTypeSerializer(I18nAwareModelSerializer):

View File

@@ -41,8 +41,8 @@ from rest_framework import routers
from pretix.api.views import cart
from .views import (
checkin, device, discount, event, exporters, idempotency, item, oauth,
order, organizer, upload, user, version, voucher, waitinglist, webhooks,
checkin, device, discount, event, exporters, item, oauth, order, organizer,
upload, user, version, voucher, waitinglist, webhooks,
)
router = routers.DefaultRouter()
@@ -133,7 +133,6 @@ urlpatterns = [
re_path(r"^device/roll$", device.RollKeyView.as_view(), name="device.roll"),
re_path(r"^device/revoke$", device.RevokeKeyView.as_view(), name="device.revoke"),
re_path(r"^device/eventselection$", device.EventSelectionView.as_view(), name="device.eventselection"),
re_path(r"^idempotency_query$", idempotency.IdempotencyQueryView.as_view(), name="idempotency.query"),
re_path(r"^upload$", upload.UploadView.as_view(), name="upload"),
re_path(r"^me$", user.MeView.as_view(), name="user.me"),
re_path(r"^version$", version.VersionView.as_view(), name="version"),

View File

@@ -25,7 +25,6 @@ from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import (
Count, Exists, F, Max, OrderBy, OuterRef, Prefetch, Q, Subquery,
prefetch_related_objects,
)
from django.db.models.functions import Coalesce
from django.http import Http404
@@ -158,7 +157,6 @@ class CheckinListViewSet(viewsets.ModelViewSet):
list=self.get_object(),
successful=False,
forced=True,
force_sent=True,
device=self.request.auth if isinstance(self.request.auth, Device) else None,
gate=self.request.auth.gate if isinstance(self.request.auth, Device) else None,
**kwargs,
@@ -281,7 +279,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = CheckinListOrderPositionSerializer
queryset = OrderPosition.all.none()
filter_backends = (ExtendedBackend, RichOrderingFilter)
ordering = (F('attendee_name_cached').asc(nulls_last=True), 'positionid')
ordering = ('attendee_name_cached', 'positionid')
ordering_fields = (
'order__code', 'order__datetime', 'positionid', 'attendee_name',
'last_checked_in', 'order__email',
@@ -409,13 +407,6 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
raise ValidationError("Invalid check-in type.")
ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
nonce = self.request.data.get('nonce')
untrusted_input = (
self.request.GET.get('untrusted_input', '') not in ('0', 'false', 'False', '')
or (isinstance(self.request.auth, Device) and 'pretixscan' in (self.request.auth.software_brand or '').lower())
)
if not self.checkinlist.all_products:
prefetch_related_objects([self.checkinlist], 'limit_products')
if 'datetime' in self.request.data:
dt = DateTimeField().to_internal_value(self.request.data.get('datetime'))
@@ -433,34 +424,20 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
forced=force,
)
raw_barcode_for_checkin = None
from_revoked_secret = False
# 1. Gather a list of positions that could be the one we looking fore, either from their ID, secret or
# parent secret
queryset = self.get_queryset(ignore_status=True, ignore_products=True).order_by(
F('addon_to').asc(nulls_first=True)
)
q = Q(secret=self.kwargs['pk'])
if self.checkinlist.addon_match:
q |= Q(addon_to__secret=self.kwargs['pk'])
if self.kwargs['pk'].isnumeric() and not untrusted_input:
q |= Q(pk=self.kwargs['pk'])
op_candidates = list(queryset.filter(q))
if not op_candidates and '+' in self.kwargs['pk']:
# In application/x-www-form-urlencoded, you can encodes space ' ' with '+' instead of '%20'.
# `id`, however, is part of a path where this technically is not allowed. Old versions of our
# scan apps still do it, so we try work around it!
q = Q(secret=self.kwargs['pk'].replace('+', ' '))
if self.checkinlist.addon_match:
q |= Q(addon_to__secret=self.kwargs['pk'].replace('+', ' '))
op_candidates = list(queryset.filter(q))
# 2. Handle the "nothing found" case: Either it's really a bogus secret that we don't know (-> error), or it
# might be a revoked one that we actually know (-> error, but with better error message and logging and
# with respecting the force option).
if not op_candidates:
try:
queryset = self.get_queryset(ignore_status=True, ignore_products=True)
if self.kwargs['pk'].isnumeric():
op = queryset.get(Q(pk=self.kwargs['pk']) | Q(secret=self.kwargs['pk']))
else:
# In application/x-www-form-urlencoded, you can encodes space ' ' with '+' instead of '%20'.
# `id`, however, is part of a path where this technically is not allowed. Old versions of our
# scan apps still do it, so we try work around it!
try:
op = queryset.get(secret=self.kwargs['pk'])
except OrderPosition.DoesNotExist:
op = queryset.get(secret=self.kwargs['pk'].replace('+', ' '))
except OrderPosition.DoesNotExist:
revoked_matches = list(self.request.event.revoked_secrets.filter(secret=self.kwargs['pk']))
if len(revoked_matches) == 0:
self.request.event.log_action('pretix.event.checkin.unknown', data={
@@ -520,11 +497,8 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
'require_attention': False,
}, status=404)
elif revoked_matches and force:
op_candidates = [revoked_matches[0].position]
if self.checkinlist.addon_match:
op_candidates += list(revoked_matches[0].position.addons.all())
op = revoked_matches[0].position
raw_barcode_for_checkin = self.kwargs['pk']
from_revoked_secret = True
else:
op = revoked_matches[0].position
op.order.log_action('pretix.event.checkin.revoked', data={
@@ -547,56 +521,6 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
}, status=400)
# 3. Handle the "multiple options found" case: Except for the unlikely case of a secret being also a valid primary
# key on the same list, we're probably dealing with the ``addon_match`` case here and need to figure out
# which add-on has the right product.
if len(op_candidates) > 1:
if self.checkinlist.addon_match and not self.checkinlist.all_products:
op_candidates_matching_product = [
op for op in op_candidates if op.item_id in {i.pk for i in self.checkinlist.limit_products.all()}
]
else:
op_candidates_matching_product = op_candidates
if len(op_candidates_matching_product) == 0:
# None of the found add-ons has the correct product, too bad! We could just error out here, but
# instead we just continue with *any* product and have it rejected by the check in perform_checkin.
# This has the advantage of a better error message.
op_candidates = [op_candidates[0]]
elif len(op_candidates_matching_product) > 1:
# It's still ambiguous, we'll error out.
# 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': dt,
'type': type,
'list': self.checkinlist.pk
}, user=self.request.user, auth=self.request.auth)
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,
'reason_explanation': None,
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
}, status=400)
else:
op_candidates = op_candidates_matching_product
op = op_candidates[0]
# 5. Pre-validate all incoming answers, handle file upload
given_answers = {}
if 'answers' in self.request.data:
aws = self.request.data.get('answers')
@@ -610,7 +534,6 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
except ValidationError:
pass
# 6. Pass to our actual check-in logic
with language(self.request.event.settings.locale):
try:
perform_checkin(
@@ -627,7 +550,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
auth=self.request.auth,
type=type,
raw_barcode=raw_barcode_for_checkin,
from_revoked_secret=from_revoked_secret,
from_revoked_secret=True,
)
except RequiredQuestionsError as e:
return Response({

View File

@@ -321,7 +321,6 @@ with scopes_disabled():
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
sales_channel = django_filters.rest_framework.CharFilter(method='sales_channel_qs')
class Meta:
model = SubEvent
@@ -354,9 +353,6 @@ with scopes_disabled():
else:
return queryset.exclude(expr)
def sales_channel_qs(self, queryset, name, value):
return queryset.filter(event__sales_channels__contains=value)
class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = SubEventSerializer

View File

@@ -1,80 +0,0 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import json
import logging
from hashlib import sha1
from django.conf import settings
from django.http import HttpResponse, JsonResponse
from rest_framework import status
from rest_framework.views import APIView
from pretix.api.models import ApiCall
logger = logging.getLogger(__name__)
class IdempotencyQueryView(APIView):
# Experimental feature, therefore undocumented for now
authentication_classes = ()
permission_classes = ()
def get(self, request, format=None):
idempotency_key = request.GET.get("key")
auth_hash_parts = '{}:{}'.format(
request.headers.get('Authorization', ''),
request.COOKIES.get(settings.SESSION_COOKIE_NAME, '')
)
auth_hash = sha1(auth_hash_parts.encode()).hexdigest()
if not idempotency_key:
return JsonResponse({
'detail': 'No idempotency key given.'
}, status=status.HTTP_404_NOT_FOUND)
try:
call = ApiCall.objects.get(
auth_hash=auth_hash,
idempotency_key=idempotency_key,
)
except ApiCall.DoesNotExist:
return JsonResponse({
'detail': 'Idempotency key not seen before.'
}, status=status.HTTP_404_NOT_FOUND)
if call.locked:
r = JsonResponse(
{'detail': 'Concurrent request with idempotency key.'},
status=status.HTTP_409_CONFLICT,
)
r['Retry-After'] = 5
return r
content = call.response_body
if isinstance(content, memoryview):
content = content.tobytes()
r = HttpResponse(
content=content,
status=call.response_code,
)
for k, v in json.loads(call.response_headers).values():
r[k] = v
return r

View File

@@ -27,9 +27,7 @@ from decimal import Decimal
import django_filters
import pytz
from django.db import transaction
from django.db.models import (
Exists, F, OuterRef, Prefetch, Q, Subquery, prefetch_related_objects,
)
from django.db.models import Exists, F, OuterRef, Prefetch, Q, Subquery
from django.db.models.functions import Coalesce, Concat
from django.http import FileResponse, HttpResponse
from django.shortcuts import get_object_or_404
@@ -204,35 +202,37 @@ class OrderViewSet(viewsets.ModelViewSet):
if 'invoice_address' not in self.request.GET.getlist('exclude'):
qs = qs.select_related('invoice_address')
qs = qs.prefetch_related(self._positions_prefetch(self.request))
return qs
def _positions_prefetch(self, request):
if request.query_params.get('include_canceled_positions', 'false') == 'true':
if self.request.query_params.get('include_canceled_positions', 'false') == 'true':
opq = OrderPosition.all
else:
opq = OrderPosition.objects
if request.query_params.get('pdf_data', 'false') == 'true':
return Prefetch(
'positions',
opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()),
'item', 'variation', 'answers', 'answers__options', 'answers__question',
'item__category', 'addon_to', 'seat',
Prefetch('addons', opq.select_related('item', 'variation', 'seat'))
if self.request.query_params.get('pdf_data', 'false') == 'true':
qs = qs.prefetch_related(
Prefetch(
'positions',
opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()),
'item', 'variation', 'answers', 'answers__options', 'answers__question',
'item__category', 'addon_to', 'seat',
Prefetch('addons', opq.select_related('item', 'variation', 'seat'))
)
)
)
else:
return Prefetch(
'positions',
opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()),
'item', 'variation',
Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options', 'question').order_by('question__position')),
'seat',
qs = qs.prefetch_related(
Prefetch(
'positions',
opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()),
'item', 'variation',
Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options', 'question').order_by('question__position')),
'seat',
)
)
)
return qs
def _get_output_provider(self, identifier):
responses = register_ticket_outputs.send(self.request.event)
for receiver, response in responses:
@@ -261,11 +261,8 @@ class OrderViewSet(viewsets.ModelViewSet):
provider = self._get_output_provider(output)
order = self.get_object()
if order.status in (Order.STATUS_CANCELED, Order.STATUS_EXPIRED):
raise PermissionDenied("Downloads are not available for canceled or expired orders.")
if order.status == Order.STATUS_PENDING and not request.event.settings.ticket_download_pending:
raise PermissionDenied("Downloads are not available for pending orders.")
if order.status != Order.STATUS_PAID:
raise PermissionDenied("Downloads are not available for unpaid orders.")
ct = CachedCombinedTicket.objects.filter(
order=order, provider=provider.identifier, file__isnull=False
@@ -619,7 +616,6 @@ class OrderViewSet(viewsets.ModelViewSet):
serializer = SimulatedOrderSerializer(order, context=serializer.context)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
prefetch_related_objects([order], self._positions_prefetch(request))
serializer = OrderSerializer(order, context=serializer.context)
order.log_action(
@@ -1123,11 +1119,8 @@ class OrderPositionViewSet(viewsets.ModelViewSet):
provider = self._get_output_provider(output)
pos = self.get_object()
if pos.order.status in (Order.STATUS_CANCELED, Order.STATUS_EXPIRED):
raise PermissionDenied("Downloads are not available for canceled or expired orders.")
if pos.order.status == Order.STATUS_PENDING and not request.event.settings.ticket_download_pending:
raise PermissionDenied("Downloads are not available for pending orders.")
if pos.order.status != Order.STATUS_PAID:
raise PermissionDenied("Downloads are not available for unpaid orders.")
if not pos.generate_ticket:
raise PermissionDenied("Downloads are not enabled for this product.")

View File

@@ -25,7 +25,7 @@ from django.db import transaction
from django.db.models import F, Q
from django.utils.timezone import now
from django_filters.rest_framework import (
BooleanFilter, CharFilter, DjangoFilterBackend, FilterSet,
BooleanFilter, DjangoFilterBackend, FilterSet,
)
from django_scopes import scopes_disabled
from rest_framework import status, viewsets
@@ -40,7 +40,6 @@ from pretix.base.models import Voucher
with scopes_disabled():
class VoucherFilter(FilterSet):
active = BooleanFilter(method='filter_active')
code = CharFilter(lookup_expr='iexact')
class Meta:
model = Voucher

View File

@@ -475,11 +475,8 @@ def base_placeholders(sender, **kwargs):
),
SimpleFunctionalMailTextPlaceholder(
'event_admission_time', ['event_or_subevent'],
lambda event_or_subevent:
date_format(event_or_subevent.date_admission.astimezone(event_or_subevent.timezone), 'TIME_FORMAT')
if event_or_subevent.date_admission
else '',
lambda event: date_format(event.date_admission.astimezone(event.timezone), 'TIME_FORMAT') if event.date_admission else '',
lambda event_or_subevent: date_format(event_or_subevent.date_admission, 'TIME_FORMAT') if event_or_subevent.date_admission else '',
lambda event: date_format(event.date_admission, 'TIME_FORMAT') if event.date_admission else '',
),
SimpleFunctionalMailTextPlaceholder(
'subevent', ['waiting_list_entry', 'event'],

View File

@@ -23,7 +23,6 @@ from .answers import * # noqa
from .dekodi import * # noqa
from .events import * # noqa
from .invoices import * # noqa
from .items import * # noqa
from .json import * # noqa
from .mail import * # noqa
from .orderlist import * # noqa

View File

@@ -1,222 +0,0 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from django.db.models import Prefetch
from django.dispatch import receiver
from django.utils.formats import date_format
from django.utils.translation import gettext_lazy as _
from openpyxl.styles import Alignment
from openpyxl.utils import get_column_letter
from ...helpers.safe_openpyxl import SafeCell
from ..channels import get_all_sales_channels
from ..exporter import ListExporter
from ..models import ItemMetaValue
from ..signals import register_data_exporters
def _max(a1, a2):
if a1 and a2:
return max(a1, a2)
return a1 or a2
def _min(a1, a2):
if a1 and a2:
return min(a1, a2)
return a1 or a2
class ItemDataExporter(ListExporter):
identifier = 'itemdata'
verbose_name = _('Product data')
def iterate_list(self, form_data):
locales = self.event.settings.locales
scs = get_all_sales_channels()
header = [
_("Product ID"),
_("Variation ID"),
_("Product category"),
_("Internal name"),
]
for l in locales:
header.append(
_("Item name") + f" ({l})"
)
for l in locales:
header.append(
_("Variation") + f" ({l})"
)
header += [
_("Active"),
_("Sales channels"),
_("Default price"),
_("Free price input"),
_("Sales tax"),
_("Is an admission ticket"),
_("Generate tickets"),
_("Waiting list"),
_("Available from"),
_("Available until"),
_("This product can only be bought using a voucher."),
_("This product will only be shown if a voucher matching the product is redeemed."),
_("Buying this product requires approval"),
_("Only sell this product as part of a bundle"),
_("Allow product to be canceled or changed"),
_("Minimum amount per order"),
_("Maximum amount per order"),
_("Requires special attention"),
_("Original price"),
_("This product is a gift card"),
_("Require a valid membership"),
_("Hide without a valid membership"),
]
props = list(self.event.item_meta_properties.all())
for p in props:
header.append(p.name)
if form_data["_format"] == "xlsx":
row = []
for h in header:
c = SafeCell(self.__ws, value=h)
c.alignment = Alignment(wrap_text=True, vertical='top')
row.append(c)
else:
row = header
yield row
for i in self.event.items.prefetch_related(
'variations',
Prefetch(
'meta_values',
ItemMetaValue.objects.select_related('property'),
to_attr='meta_values_cached'
)
).select_related('category', 'tax_rule'):
m = i.meta_data
vars = list(i.variations.all())
if vars:
for v in vars:
row = [
i.pk,
v.pk,
str(i.category) if i.category else "",
i.internal_name or "",
]
for l in locales:
row.append(i.name.localize(l))
for l in locales:
row.append(v.value.localize(l))
row += [
_("Yes") if i.active and v.active else "",
", ".join([str(sn.verbose_name) for s, sn in scs.items() if s in i.sales_channels and s in v.sales_channels]),
v.default_price or i.default_price,
_("Yes") if i.free_price else "",
str(i.tax_rule) if i.tax_rule else "",
_("Yes") if i.admission else "",
_("Yes") if i.generate_tickets else (_("Default") if i.generate_tickets is None else ""),
_("Yes") if i.allow_waitinglist else "",
date_format(_max(i.available_from, v.available_from).astimezone(self.timezone),
"SHORT_DATETIME_FORMAT") if i.available_from or v.available_from else "",
date_format(_min(i.available_until, v.available_until).astimezone(self.timezone),
"SHORT_DATETIME_FORMAT") if i.available_until or v.available_until else "",
_("Yes") if i.require_voucher else "",
_("Yes") if i.hide_without_voucher or v.hide_without_voucher else "",
_("Yes") if i.require_approval or v.require_approval else "",
_("Yes") if i.require_bundling else "",
_("Yes") if i.allow_cancel else "",
i.min_per_order if i.min_per_order is not None else "",
i.max_per_order if i.max_per_order is not None else "",
_("Yes") if i.checkin_attention else "",
v.original_price or i.original_price or "",
_("Yes") if i.issue_giftcard else "",
_("Yes") if i.require_membership or v.require_membership else "",
_("Yes") if i.require_membership_hidden or v.require_membership_hidden else "",
]
row += [
m.get(p.name, '') for p in props
]
yield row
else:
row = [
i.pk,
"",
str(i.category) if i.category else "",
i.internal_name or "",
]
for l in locales:
row.append(i.name.localize(l))
for l in locales:
row.append("")
row += [
_("Yes") if i.active else "",
", ".join([str(sn.verbose_name) for s, sn in scs.items() if s in i.sales_channels]),
i.default_price,
_("Yes") if i.free_price else "",
str(i.tax_rule) if i.tax_rule else "",
_("Yes") if i.admission else "",
_("Yes") if i.generate_tickets else (_("Default") if i.generate_tickets is None else ""),
_("Yes") if i.allow_waitinglist else "",
date_format(i.available_from.astimezone(self.timezone),
"SHORT_DATETIME_FORMAT") if i.available_from else "",
date_format(i.available_until.astimezone(self.timezone),
"SHORT_DATETIME_FORMAT") if i.available_until else "",
_("Yes") if i.require_voucher else "",
_("Yes") if i.hide_without_voucher else "",
_("Yes") if i.require_approval else "",
_("Yes") if i.require_bundling else "",
_("Yes") if i.allow_cancel else "",
i.min_per_order if i.min_per_order is not None else "",
i.max_per_order if i.max_per_order is not None else "",
_("Yes") if i.checkin_attention else "",
i.original_price or "",
_("Yes") if i.issue_giftcard else "",
_("Yes") if i.require_membership else "",
_("Yes") if i.require_membership_hidden else "",
]
row += [
m.get(p.name, '') for p in props
]
yield row
def get_filename(self):
return '{}_products'.format(self.events.first().organizer.slug)
def prepare_xlsx_sheet(self, ws):
self.__ws = ws
ws.freeze_panes = 'A1'
ws.column_dimensions['C'].width = 25
ws.column_dimensions['D'].width = 25
for i in range(len(self.event.settings.locales)):
ws.column_dimensions[get_column_letter(5 + 2 * i + 0)].width = 25
ws.column_dimensions[get_column_letter(5 + 2 * i + 1)].width = 25
ws.column_dimensions[get_column_letter(5 + 2 * len(self.event.settings.locales) + 1)].width = 25
ws.row_dimensions[1].height = 40
@receiver(register_data_exporters, dispatch_uid="exporter_itemdata")
def register_itemdata_exporter(sender, **kwargs):
return ItemDataExporter

View File

@@ -259,7 +259,7 @@ class OrderListExporter(MultiSheetListExporter):
payment_providers=Subquery(p_providers, output_field=CharField()),
invoice_numbers=Subquery(i_numbers, output_field=CharField()),
pcnt=Subquery(s, output_field=IntegerField())
).select_related('invoice_address', 'customer')
).select_related('invoice_address')
qs = self._date_filter(qs, form_data, rel='')
@@ -268,8 +268,8 @@ class OrderListExporter(MultiSheetListExporter):
tax_rates = self._get_all_tax_rates(qs)
headers = [
_('Event slug'), _('Order code'), _('Order total'), _('Status'), _('Email'), _('Phone number'),
_('Order date'), _('Order time'), _('Company'), _('Name'),
_('Event slug'), _('Order code'), _('Order total'), _('Status'), _('Email'), _('Phone number'), _('Order date'),
_('Order time'), _('Company'), _('Name'),
]
name_scheme = PERSON_NAME_SCHEMES[self.event.settings.name_scheme] if not self.is_multievent else None
if name_scheme and len(name_scheme['fields']) > 1:
@@ -294,7 +294,6 @@ class OrderListExporter(MultiSheetListExporter):
headers.append(_('Follow-up date'))
headers.append(_('Positions'))
headers.append(_('E-mail address verified'))
headers.append(_('External customer ID'))
headers.append(_('Payment providers'))
if form_data.get('include_payment_amounts'):
payment_methods = self._get_all_payment_methods(qs)
@@ -401,7 +400,6 @@ class OrderListExporter(MultiSheetListExporter):
row.append(order.custom_followup_at.strftime("%Y-%m-%d") if order.custom_followup_at else "")
row.append(order.pcnt)
row.append(_('Yes') if order.email_known_to_work else _('No'))
row.append(str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '')
row.append(', '.join([
str(self.providers.get(p, p)) for p in sorted(set((order.payment_providers or '').split(',')))
if p and p != 'free'
@@ -426,13 +424,13 @@ class OrderListExporter(MultiSheetListExporter):
).values(
'm'
).order_by()
qs = OrderFee.all.filter(
qs = OrderFee.objects.filter(
order__event__in=self.events,
).annotate(
payment_providers=Subquery(p_providers, output_field=CharField()),
).select_related('order', 'order__invoice_address', 'order__customer', 'tax_rule')
).select_related('order', 'order__invoice_address', 'tax_rule')
if form_data['paid_only']:
qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False)
qs = qs.filter(order__status=Order.STATUS_PAID)
qs = self._date_filter(qs, form_data, rel='order__')
@@ -461,7 +459,6 @@ class OrderListExporter(MultiSheetListExporter):
_('Address'), _('ZIP code'), _('City'), _('Country'), pgettext('address', 'State'), _('VAT ID'),
]
headers.append(_('External customer ID'))
headers.append(_('Payment providers'))
yield headers
@@ -472,7 +469,7 @@ class OrderListExporter(MultiSheetListExporter):
row = [
self.event_object_cache[order.event_id].slug,
order.code,
_("canceled") if op.canceled else order.get_status_display(),
order.get_status_display(),
order.email,
str(order.phone) if order.phone else '',
order.datetime.astimezone(tz).strftime('%Y-%m-%d'),
@@ -505,7 +502,6 @@ class OrderListExporter(MultiSheetListExporter):
]
except InvoiceAddress.DoesNotExist:
row += [''] * (8 + (len(name_scheme['fields']) if name_scheme and len(name_scheme['fields']) > 1 else 0))
row.append(str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '')
row.append(', '.join([
str(self.providers.get(p, p)) for p in sorted(set((op.payment_providers or '').split(',')))
if p and p != 'free'
@@ -522,19 +518,19 @@ class OrderListExporter(MultiSheetListExporter):
).values(
'm'
).order_by()
base_qs = OrderPosition.all.filter(
base_qs = OrderPosition.objects.filter(
order__event__in=self.events,
)
qs = base_qs.annotate(
payment_providers=Subquery(p_providers, output_field=CharField()),
).select_related(
'order', 'order__invoice_address', 'order__customer', 'item', 'variation',
'order', 'order__invoice_address', 'item', 'variation',
'voucher', 'tax_rule'
).prefetch_related(
'answers', 'answers__question', 'answers__options'
)
if form_data['paid_only']:
qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False)
qs = qs.filter(order__status=Order.STATUS_PAID)
qs = self._date_filter(qs, form_data, rel='order__')
@@ -615,7 +611,6 @@ class OrderListExporter(MultiSheetListExporter):
headers += [
_('Sales channel'), _('Order locale'),
_('E-mail address verified'),
_('External customer ID'),
_('Payment providers'),
]
@@ -633,7 +628,7 @@ class OrderListExporter(MultiSheetListExporter):
self.event_object_cache[order.event_id].slug,
order.code,
op.positionid,
_("canceled") if op.canceled else order.get_status_display(),
order.get_status_display(),
order.email,
str(order.phone) if order.phone else '',
order.datetime.astimezone(tz).strftime('%Y-%m-%d'),
@@ -735,8 +730,7 @@ class OrderListExporter(MultiSheetListExporter):
row += [
order.sales_channel,
order.locale,
_('Yes') if order.email_known_to_work else _('No'),
str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '',
_('Yes') if order.email_known_to_work else _('No')
]
row.append(', '.join([
str(self.providers.get(p, p)) for p in sorted(set((op.payment_providers or '').split(',')))

View File

@@ -196,16 +196,10 @@ class SecretKeySettingsWidget(forms.TextInput):
attrs.update({
'autocomplete': 'new-password' # see https://bugs.chromium.org/p/chromium/issues/detail?id=370363#c7
})
self.__reflect_value = False
super().__init__(attrs)
def value_from_datadict(self, data, files, name):
value = super().value_from_datadict(data, files, name)
self.__reflect_value = value and value != SECRET_REDACTED
return value
def get_context(self, name, value, attrs):
if value and not self.__reflect_value:
if value:
value = SECRET_REDACTED
return super().get_context(name, value, attrs)

View File

@@ -253,7 +253,7 @@ class NamePartsFormField(forms.MultiValueField):
if self.require_all_fields and not all(v for v in value):
raise forms.ValidationError(self.error_messages['incomplete'], code='required')
if sum(len(v) for v in value.values() if v) > 250:
if sum(len(v) for v in value if v) > 250:
raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length')
return value
@@ -429,7 +429,7 @@ class PortraitImageWidget(UploadedFileWidget):
def value_from_datadict(self, data, files, name):
d = super().value_from_datadict(data, files, name)
if d is not None and d is not False:
if d is not None:
d._cropdata = json.loads(data.get(name + '_cropdata', '{}') or '{}')
return d

View File

@@ -510,7 +510,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
return story
def _get_story(self, doc):
has_taxes = any(il.tax_value for il in self.invoice.lines.all()) or self.invoice.reverse_charge
has_taxes = any(il.tax_value for il in self.invoice.lines.all())
story = [
NextPageTemplate('FirstPage'),

View File

@@ -76,10 +76,6 @@ class LocaleMiddleware(MiddlewareMixin):
if lang.startswith(firstpart + '-'):
language = lang
break
if language not in settings_holder.settings.locales:
# This seems redundant, but can happen in the rare edge case that settings.locale is (wrongfully)
# not part of settings.locales
language = settings_holder.settings.locales[0]
if '-' not in language and settings_holder.settings.region:
language += '-' + settings_holder.settings.region
else:

View File

@@ -4,6 +4,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.db import migrations, models
from django_mysql.checks import mysql_connections
from django_mysql.utils import connection_is_mariadb
def set_attendee_name_parts(apps, schema_editor):
@@ -30,7 +31,7 @@ def check_mysqlversion(apps, schema_editor):
conns = list(mysql_connections())
found = 'Unknown version'
for alias, conn in conns:
if hasattr(conn, 'mysql_is_mariadb') and conn.mysql_is_mariadb and hasattr(conn, 'mysql_version'):
if connection_is_mariadb(conn) and hasattr(conn, 'mysql_version'):
if conn.mysql_version >= (10, 2, 7):
any_conn_works = True
else:

View File

@@ -1,23 +0,0 @@
# Generated by Django 3.2.12 on 2022-04-28 08:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0213_discount_condition_ignore_voucher_discounted'),
]
operations = [
migrations.AddField(
model_name='customer',
name='external_identifier',
field=models.CharField(max_length=255, null=True),
),
migrations.AddField(
model_name='customer',
name='notes',
field=models.TextField(null=True),
),
]

View File

@@ -1,22 +0,0 @@
# Generated by Django 3.2.12 on 2022-05-12 15:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0214_customer_notes_ext_id'),
]
operations = [
migrations.AlterField(
model_name='customer',
name='identifier',
field=models.CharField(db_index=True, max_length=190),
),
migrations.AlterUniqueTogether(
name='customer',
unique_together={('organizer', 'email'), ('organizer', 'identifier')},
),
]

View File

@@ -1,18 +0,0 @@
# Generated by Django 3.2.12 on 2022-04-29 13:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0215_customer_organizer_identifier_unique'),
]
operations = [
migrations.AddField(
model_name='checkin',
name='force_sent',
field=models.BooleanField(default=False, null=True),
),
]

View File

@@ -1,33 +0,0 @@
# Generated by Django 3.2.12 on 2022-06-15 08:10
import django.db.models.deletion
import i18nfield.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0216_checkin_forced_sent'),
]
operations = [
migrations.CreateModel(
name='OrganizerFooterLink',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
('label', i18nfield.fields.I18nCharField(max_length=200)),
('url', models.URLField()),
('organizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='footer_links', to='pretixbase.organizer')),
],
),
migrations.CreateModel(
name='EventFooterLink',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
('label', i18nfield.fields.I18nCharField(max_length=200)),
('url', models.URLField()),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='footer_links', to='pretixbase.event')),
],
),
]

View File

@@ -1,18 +0,0 @@
# Generated by Django 3.2.2 on 2022-06-29 17:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0217_eventfooterlink_organizerfooterlink'),
]
operations = [
migrations.AddField(
model_name='checkinlist',
name='addon_match',
field=models.BooleanField(default=False),
),
]

View File

@@ -56,12 +56,6 @@ class CheckinList(LoggedModel):
default=False,
help_text=_('With this option, people will be able to check in even if the '
'order has not been paid.'))
addon_match = models.BooleanField(
verbose_name=_('Allow checking in add-on tickets by scanning the main ticket'),
default=False,
help_text=_('A scan will only be possible if the check-in list is configured such that there is always exactly '
'one matching add-on ticket. Ambiguous scans will be rejected..')
)
gates = models.ManyToManyField(
'Gate', verbose_name=_("Gates"), blank=True,
help_text=_("Does not have any effect for the validation of tickets, only for the automatic configuration of "
@@ -264,7 +258,6 @@ class Checkin(models.Model):
REASON_REVOKED = 'revoked'
REASON_INCOMPLETE = 'incomplete'
REASON_ALREADY_REDEEMED = 'already_redeemed'
REASON_AMBIGUOUS = 'ambiguous'
REASON_ERROR = 'error'
REASONS = (
(REASON_CANCELED, _('Order canceled')),
@@ -275,7 +268,6 @@ class Checkin(models.Model):
(REASON_INCOMPLETE, _('Information required')),
(REASON_ALREADY_REDEEMED, _('Ticket already used')),
(REASON_PRODUCT, _('Ticket type not allowed here')),
(REASON_AMBIGUOUS, _('Ticket code is ambiguous on list')),
(REASON_ERROR, _('Server error')),
)
@@ -334,13 +326,7 @@ class Checkin(models.Model):
type = models.CharField(max_length=100, choices=CHECKIN_TYPES, default=TYPE_ENTRY)
nonce = models.CharField(max_length=190, null=True, blank=True)
# Whether or not the scan was made offline
force_sent = models.BooleanField(default=False, null=True, blank=True)
# Whether the scan was made offline AND would have not been possible online
forced = models.BooleanField(default=False)
device = models.ForeignKey(
'pretixbase.Device', related_name='checkins', on_delete=models.PROTECT, null=True, blank=True
)

View File

@@ -24,7 +24,6 @@ from django.conf import settings
from django.contrib.auth.hashers import (
check_password, is_password_usable, make_password,
)
from django.core.validators import RegexValidator
from django.db import models
from django.db.models import F, Q
from django.utils.crypto import get_random_string, salted_hmac
@@ -45,18 +44,7 @@ class Customer(LoggedModel):
"""
id = models.BigAutoField(primary_key=True)
organizer = models.ForeignKey(Organizer, related_name='customers', on_delete=models.CASCADE)
identifier = models.CharField(
max_length=190,
db_index=True,
help_text=_('You can enter any value here to make it easier to match the data with other sources. If you do '
'not input one, we will generate one automatically.'),
validators=[
RegexValidator(
regex=r"^[a-zA-Z0-9]([a-zA-Z0-9.\-_]*[a-zA-Z0-9])?$",
message=_("The identifier may only contain letters, numbers, dots, dashes, and underscores. It must start and end with a letter or number."),
),
],
)
identifier = models.CharField(max_length=190, db_index=True, unique=True)
email = models.EmailField(db_index=True, null=True, blank=False, verbose_name=_('E-mail'), max_length=190)
phone = PhoneNumberField(null=True, blank=True, verbose_name=_('Phone number'))
password = models.CharField(verbose_name=_('Password'), max_length=128)
@@ -71,13 +59,11 @@ class Customer(LoggedModel):
default=settings.LANGUAGE_CODE,
verbose_name=_('Language'))
last_modified = models.DateTimeField(auto_now=True)
external_identifier = models.CharField(max_length=255, verbose_name=_('External identifier'), null=True, blank=True)
notes = models.TextField(verbose_name=_('Notes'), null=True, blank=True)
objects = ScopedManager(organizer='organizer')
class Meta:
unique_together = [['organizer', 'email'], ['organizer', 'identifier']]
unique_together = [['organizer', 'email']]
ordering = ('email',)
def get_email_field_name(self):
@@ -104,8 +90,6 @@ class Customer(LoggedModel):
self.name_cached = ''
self.email = None
self.phone = None
self.external_identifier = None
self.notes = None
self.save()
self.all_logentries().update(data={}, shredded=True)
self.orders.all().update(customer=None)

View File

@@ -179,7 +179,6 @@ class Device(LoggedModel):
return {
'can_view_orders',
'can_change_orders',
'can_view_vouchers',
'can_manage_gift_cards'
}

View File

@@ -608,14 +608,11 @@ class Event(EventMixin, LoggedModel):
return super().presale_has_ended
def delete_all_orders(self, really=False):
from .orders import (
OrderFee, OrderPayment, OrderPosition, OrderRefund, Transaction,
)
from .orders import OrderFee, OrderPayment, OrderPosition, OrderRefund
if not really:
raise TypeError("Pass really=True as a parameter.")
Transaction.objects.filter(order__event=self).delete()
OrderPosition.all.filter(order__event=self, addon_to__isnull=False).delete()
OrderPosition.all.filter(order__event=self).delete()
OrderFee.objects.filter(order__event=self).delete()
@@ -721,11 +718,6 @@ class Event(EventMixin, LoggedModel):
self.save()
self.log_action('pretix.object.cloned', data={'source': other.slug, 'source_id': other.pk})
for fl in EventFooterLink.objects.filter(event=other):
fl.pk = None
fl.event = self
fl.save(force_insert=True)
tax_map = {}
for t in other.tax_rules.all():
tax_map[t.pk] = t
@@ -768,7 +760,7 @@ class Event(EventMixin, LoggedModel):
if i.grant_membership_type and other.organizer_id != self.organizer_id:
i.grant_membership_type = None
i.save() # no force_insert since i.picture.save could have already inserted
i.save(force_insert=True)
i.log_action('pretix.object.cloned')
if require_membership_types and other.organizer_id == self.organizer_id:
@@ -1234,7 +1226,7 @@ class Event(EventMixin, LoggedModel):
self.set_active_plugins(plugins_active)
plugins_available = self.get_available_plugins()
if module in plugins_available and hasattr(plugins_available[module].app, 'uninstalled'):
if hasattr(plugins_available[module].app, 'uninstalled'):
getattr(plugins_available[module].app, 'uninstalled')(self)
regenerate_css.apply_async(args=(self.pk,))
@@ -1620,25 +1612,3 @@ class SubEventMetaValue(LoggedModel):
super().save(*args, **kwargs)
if self.subevent:
self.subevent.event.cache.clear()
class EventFooterLink(models.Model):
"""
A footer link assigned to an event.
"""
event = models.ForeignKey('Event', on_delete=models.CASCADE, related_name='footer_links')
label = I18nCharField(
max_length=200,
verbose_name=_("Link text"),
)
url = models.URLField(
verbose_name=_("Link URL"),
)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
self.event.cache.clear()
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.event.cache.clear()

View File

@@ -1243,13 +1243,7 @@ class Question(LoggedModel):
max_length=190,
verbose_name=_("Internal identifier"),
help_text=_('You can enter any value here to make it easier to match the data with other sources. If you do '
'not input one, we will generate one automatically.'),
validators=[
RegexValidator(
regex=r"^[a-zA-Z0-9.\-_]+$",
message=_("The identifier may only contain letters, numbers, dots, dashes, and underscores."),
),
],
'not input one, we will generate one automatically.')
)
help_text = I18nTextField(
verbose_name=_("Help text"),
@@ -1467,17 +1461,7 @@ class Question(LoggedModel):
class QuestionOption(models.Model):
question = models.ForeignKey('Question', related_name='options', on_delete=models.CASCADE)
identifier = models.CharField(
max_length=190,
help_text=_('You can enter any value here to make it easier to match the data with other sources. If you do '
'not input one, we will generate one automatically.'),
validators=[
RegexValidator(
regex=r"^[a-zA-Z0-9.\-_]+$",
message=_("The identifier may only contain letters, numbers, dots, dashes, and underscores."),
),
],
)
identifier = models.CharField(max_length=190)
answer = I18nCharField(verbose_name=_('Answer'))
position = models.IntegerField(default=0)

View File

@@ -843,7 +843,7 @@ class Order(LockModel, LoggedModel):
if terms:
term_last = min(terms)
else:
return None
term_last = None
else:
term_last = term_last.datetime(self.event).date()
term_last = make_aware(datetime.combine(
@@ -1588,7 +1588,7 @@ class OrderPayment(models.Model):
if status_change:
self.order.create_transactions()
def fail(self, info=None, user=None, auth=None, log_data=None):
def fail(self, info=None, user=None, auth=None):
"""
Marks the order as failed and sets info to ``info``, but only if the order is in ``created`` or ``pending``
state. This is equivalent to setting ``state`` to ``OrderPayment.PAYMENT_STATE_FAILED`` and logging a failure,
@@ -1616,7 +1616,6 @@ class OrderPayment(models.Model):
'local_id': self.local_id,
'provider': self.provider,
'info': info,
'data': log_data,
}, user=user, auth=auth)
def confirm(self, count_waitinglist=True, send_mail=True, force=False, user=None, auth=None, mail_text='',

View File

@@ -46,7 +46,6 @@ from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.timezone import get_current_timezone, make_aware, now
from django.utils.translation import gettext_lazy as _
from i18nfield.fields import I18nCharField
from pretix.base.models.base import LoggedModel
from pretix.base.validators import OrganizerSlugBanlistValidator
@@ -465,25 +464,3 @@ class TeamAPIToken(models.Model):
return self.get_events_with_any_permission()
else:
return self.team.organizer.events.none()
class OrganizerFooterLink(models.Model):
"""
A footer link assigned to an organizer.
"""
organizer = models.ForeignKey('Organizer', on_delete=models.CASCADE, related_name='footer_links')
label = I18nCharField(
max_length=200,
verbose_name=_("Link text"),
)
url = models.URLField(
verbose_name=_("Link URL"),
)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
self.organizer.cache.clear()
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.organizer.cache.clear()

View File

@@ -55,7 +55,7 @@ from django.utils.formats import date_format
from django.utils.functional import SimpleLazyObject
from django.utils.html import conditional_escape
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _, pgettext
from django.utils.translation import gettext_lazy as _
from i18nfield.strings import LazyI18nString
from PyPDF2 import PdfFileReader
from pytz import timezone
@@ -521,19 +521,12 @@ def variables_from_questions(sender, *args, **kwargs):
def _get_attendee_name_part(key, op, order, ev):
if isinstance(key, tuple):
parts = [_get_attendee_name_part(c[0], op, order, ev) for c in key if not (c[0] == 'salutation' and op.attendee_name_parts.get(c[0], '') == "Mx")]
return ' '.join(p for p in parts if p)
value = op.attendee_name_parts.get(key, '')
if key == 'salutation':
return pgettext('person_name_salutation', value)
return value
return ' '.join(p for p in [_get_attendee_name_part(c[0], op, order, ev) for c in key] if p)
return op.attendee_name_parts.get(key, '')
def _get_ia_name_part(key, op, order, ev):
value = order.invoice_address.name_parts.get(key, '') if getattr(order, 'invoice_address', None) else ''
if key == 'salutation' and value:
return pgettext('person_name_salutation', value)
return value
return order.invoice_address.name_parts.get(key, '') if getattr(order, 'invoice_address', None) else ''
def get_images(event):
@@ -549,14 +542,6 @@ def get_variables(event):
v = copy.copy(DEFAULT_VARIABLES)
scheme = PERSON_NAME_SCHEMES[event.settings.name_scheme]
concatenation_for_salutation = scheme.get("concatenation_for_salutation", scheme["concatenation"])
v['attendee_name_for_salutation'] = {
'label': _("Attendee name for salutation"),
'editor_sample': _("Mr Doe"),
'evaluate': lambda op, order, ev: concatenation_for_salutation(op.attendee_name_parts or {})
}
for key, label, weight in scheme['fields']:
v['attendee_name_%s' % key] = {
'label': _("Attendee name: {part}").format(part=label),
@@ -574,12 +559,6 @@ def get_variables(event):
v['invoice_name']['editor_sample'] = scheme['concatenation'](scheme['sample'])
v['attendee_name']['editor_sample'] = scheme['concatenation'](scheme['sample'])
v['invoice_name_for_salutation'] = {
'label': _("Invoice address name for salutation"),
'editor_sample': _("Mr Doe"),
'evaluate': lambda op, order, ev: concatenation_for_salutation(order.invoice_address.name_parts if getattr(order, 'invoice_address', None) else {})
}
for key, label, weight in scheme['fields']:
v['invoice_name_%s' % key] = {
'label': _("Invoice address name: {part}").format(part=label),
@@ -734,6 +713,7 @@ class Renderer:
text = o['text']
def replace(x):
print(x.group(1))
if x.group(1).startswith('itemmeta:'):
return op.item.meta_data.get(x.group(1)[9:]) or ''
elif x.group(1).startswith('meta:'):
@@ -831,10 +811,9 @@ class Renderer:
textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255),
alignment=align_map[o['align']]
)
# add an almost-invisible space &hairsp; after hyphens as word-wrap in ReportLab only works on space chars
text = conditional_escape(
self._get_text_content(op, order, o) or "",
).replace("\n", "<br/>\n").replace("-", "-&hairsp;")
).replace("\n", "<br/>\n")
# reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper
# to resolve all ligatures and python-bidi to switch RTL texts.

View File

@@ -143,8 +143,8 @@ class Sig1TicketSecretGenerator(BaseTicketSecretGenerator):
The resulting string is REVERSED, to avoid all secrets of same length beginning with the same 10
characters, which would make it impossible to search for secrets manually.
"""
verbose_name = _('pretix signature scheme 1 (for very large events, changes semantics of offline scanning '
'please refer to documentation or support for details)')
verbose_name = _('pretix signature scheme 1 (for very large events, does not work with pretixSCAN on iOS and '
'changes semantics of offline scanning please refer to documentation or support for details)')
identifier = 'pretix_sig1'
use_revocation_list = True

View File

@@ -447,10 +447,7 @@ class CartManager:
try:
voucher = self.event.vouchers.get(code__iexact=voucher_code.strip())
except Voucher.DoesNotExist:
if self.event.organizer.accepted_gift_cards.filter(secret__iexact=voucher_code).exists():
raise CartError(error_messages['gift_card'])
else:
raise CartError(error_messages['voucher_invalid'])
raise CartError(error_messages['voucher_invalid'])
voucher_use_diff = Counter()
ops = []

View File

@@ -796,7 +796,6 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
gate=device.gate if device else None,
nonce=nonce,
forced=force and (not entry_allowed or from_revoked_secret),
force_sent=force,
raw_barcode=raw_barcode,
)
op.order.log_action('pretix.event.checkin', data={

View File

@@ -412,9 +412,8 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
logger.exception('Could not attach invoice to email')
pass
if attach_size < settings.FILE_UPLOAD_MAX_SIZE_EMAIL_ATTACHMENT - 1:
# Do not attach more than (limit - 1 MB) in tickets (1MB space for invoice, email itself, …),
# it will bounce way to often.
if attach_size < settings.FILE_UPLOAD_MAX_SIZE_EMAIL_ATTACHMENT:
# Do not attach more than 4MB, it will bounce way to often.
for a in args:
try:
email.attach(*a)

View File

@@ -2304,11 +2304,6 @@ class OrderChangeManager:
# Do nothing
return
# Clear prefetched objects cache of order. We're going to modify the positions and fees and we have no guarantee
# that every operation tuple points to a position/fee instance that has been fetched from the same object cache,
# so it's dangerous to keep the cache around.
self.order._prefetched_objects_cache = {}
# finally, incorporate difference in payment fees
self._payment_fee_diff()

View File

@@ -132,7 +132,6 @@ def generate_seats(event, subevent, plan, mapping, blocked_guids=None):
'already used in a voucher.', s.name))
Seat.objects.bulk_create(create_seats)
CartPosition.objects.filter(addon_to__seat__in=[s.pk for s in current_seats.values()]).delete()
CartPosition.objects.filter(seat__in=[s.pk for s in current_seats.values()]).delete()
OrderPosition.all.filter(
Q(canceled=True) | Q(order__status__in=(Order.STATUS_CANCELED, Order.STATUS_EXPIRED)),

View File

@@ -96,7 +96,6 @@ ALLOWED_ATTRIBUTES = {
'div': ['class'],
'p': ['class'],
'span': ['class', 'title'],
'ol': ['start'],
# Update doc/user/markdown.rst if you change this!
}

View File

@@ -84,17 +84,13 @@ def timeline_for_event(event, subevent=None):
edit_url=ev_edit_url
))
tl.append(TimelineEvent(
event=event, subevent=subevent,
datetime=(
ev.presale_end or ev.date_to or ev.date_from.astimezone(ev.timezone).replace(hour=23, minute=59, second=59)
),
description='{}{}'.format(
pgettext_lazy('timeline', 'End of ticket sales'),
f" ({pgettext_lazy('timeline', 'automatically because the event is over and no end of presale has been configured')})" if not ev.presale_end else ""
),
edit_url=ev_edit_url
))
if ev.presale_end:
tl.append(TimelineEvent(
event=event, subevent=subevent,
datetime=ev.presale_end,
description=pgettext_lazy('timeline', 'End of ticket sales'),
edit_url=ev_edit_url
))
rd = event.settings.get('last_order_modification_date', as_type=RelativeDateWrapper)
if rd:

View File

@@ -29,15 +29,13 @@ from celery.result import AsyncResult
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.http import HttpResponse, JsonResponse, QueryDict
from django.http import JsonResponse, QueryDict
from django.shortcuts import redirect, render
from django.test import RequestFactory
from django.utils import timezone, translation
from django.utils.timezone import get_current_timezone
from django.utils.translation import get_language, gettext as _
from django.views import View
from django.views.generic import FormView
from redis import ResponseError
from pretix.base.models import User
from pretix.base.services.tasks import ProfiledEventTask
@@ -70,11 +68,6 @@ class AsyncMixin:
res.get(timeout=timeout, propagate=False)
except celery.exceptions.TimeoutError:
pass
except ResponseError:
# There is a long-standing concurrency issue in either celery or redis-py that hasn't been fixed
# yet. Instead of crashing, we can ignore it and the client will retry their request and hopefully
# it is fixed next time.
logger.warning('Ignored ResponseError in AsyncResult.get()')
except ConnectionError:
# Redis probably just restarted, let's just report not ready and retry next time
data = self._ajax_response_data()
@@ -313,94 +306,3 @@ class AsyncFormView(AsyncMixin, FormView):
else:
return self.error(res.info)
return redirect(self.get_check_url(res.id, False))
class AsyncPostView(AsyncMixin, View):
"""
View variant in which instead of ``post``, an ``async_post`` is executed in a celery task.
Note that this places some severe limitations on the form and the view, e.g. ``async_post`` may not
depend on the request object unless specifically supported by this class. File upload is currently also
not supported.
"""
known_errortypes = ['ValidationError']
expected_exceptions = (ValidationError,)
task_base = ProfiledEventTask
def __init_subclass__(cls):
def async_execute(self, *, request_path, url_args, url_kwargs, query_string, post_data, locale, tz,
organizer=None, event=None, user=None, session_key=None):
view_instance = cls()
req = RequestFactory().post(
request_path + '?' + query_string,
data=post_data,
content_type='application/x-www-form-urlencoded'
)
view_instance.request = req
if event:
view_instance.request.event = event
view_instance.request.organizer = event.organizer
elif organizer:
view_instance.request.organizer = organizer
if user:
view_instance.request.user = User.objects.get(pk=user) if isinstance(user, int) else user
if session_key:
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore
view_instance.request.session = self.SessionStore(session_key)
with translation.override(locale), timezone.override(pytz.timezone(tz)):
return view_instance.async_post(view_instance.request, *url_args, **url_kwargs)
cls.async_execute = app.task(
base=cls.task_base,
bind=True,
name=cls.__module__ + '.' + cls.__name__ + '.async_execute',
throws=cls.expected_exceptions
)(async_execute)
def async_post(self, request, *args, **kwargs):
pass
def get(self, request, *args, **kwargs):
if 'async_id' in request.GET and settings.HAS_CELERY:
return self.get_result(request)
return HttpResponse(status=405)
def post(self, request, *args, **kwargs):
if request.FILES:
raise TypeError('File upload currently not supported in AsyncPostView')
kwargs = {
'request_path': self.request.path,
'query_string': self.request.GET.urlencode(),
'post_data': self.request.POST.urlencode(),
'locale': get_language(),
'url_args': args,
'url_kwargs': kwargs,
'tz': get_current_timezone().zone,
}
if hasattr(self.request, 'organizer'):
kwargs['organizer'] = self.request.organizer.pk
if self.request.user.is_authenticated:
kwargs['user'] = self.request.user.pk
if hasattr(self.request, 'event'):
kwargs['event'] = self.request.event.pk
if hasattr(self.request, 'session'):
kwargs['session_key'] = self.request.session.session_key
try:
res = type(self).async_execute.apply_async(kwargs=kwargs)
except ConnectionError:
# Task very likely not yet sent, due to redis restarting etc. Let's try once again
res = type(self).async_execute.apply_async(kwargs=kwargs)
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
data = self._return_ajax_result(res)
data['check_url'] = self.get_check_url(res.id, True)
return JsonResponse(data)
else:
if res.ready():
if res.successful() and not isinstance(res.info, Exception):
return self.success(res.info)
else:
return self.error(res.info)
return redirect(self.get_check_url(res.id, False))

View File

@@ -22,10 +22,9 @@
from datetime import datetime, timedelta
from django import forms
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.utils.timezone import get_current_timezone, make_aware, now
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django.utils.translation import pgettext_lazy
from django_scopes.forms import (
SafeModelChoiceField, SafeModelMultipleChoiceField,
)
@@ -110,7 +109,6 @@ class CheckinListForm(forms.ModelForm):
'rules',
'gates',
'exit_all_at',
'addon_match',
]
widgets = {
'limit_products': forms.CheckboxSelectMultiple(attrs={
@@ -132,12 +130,6 @@ class CheckinListForm(forms.ModelForm):
def clean(self):
d = super().clean()
d['rules'] = CheckinList.validate_rules(d.get('rules'))
if d.get('addon_match') and d.get('all_products'):
raise ValidationError(_('If you allow checking in add-on tickets by scanning the main ticket, you must '
'select a specific set of products for this check-in list, only including the '
'possible add-on products.'))
return d

View File

@@ -41,9 +41,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.db.models import Prefetch, Q, prefetch_related_objects
from django.forms import (
CheckboxSelectMultiple, formset_factory, inlineformset_factory,
)
from django.forms import CheckboxSelectMultiple, formset_factory
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.html import escape
@@ -60,7 +58,7 @@ from pretix.base.channels import get_all_sales_channels
from pretix.base.email import get_available_placeholders
from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
from pretix.base.models import Event, Organizer, TaxRule, Team
from pretix.base.models.event import EventFooterLink, EventMetaValue, SubEvent
from pretix.base.models.event import EventMetaValue, SubEvent
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
from pretix.base.settings import (
PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS, validate_event_settings,
@@ -1486,25 +1484,3 @@ ConfirmTextFormset = formset_factory(
formset=BaseConfirmTextFormSet,
can_order=True, can_delete=True, extra=0
)
class EventFooterLinkForm(I18nModelForm):
class Meta:
model = EventFooterLink
fields = ('label', 'url')
class BaseEventFooterLinkFormSet(I18nFormSetMixin, forms.BaseInlineFormSet):
def __init__(self, *args, **kwargs):
event = kwargs.pop('event', None)
if event:
kwargs['locales'] = event.settings.get('locales')
super().__init__(*args, **kwargs)
EventFooterLinkFormset = inlineformset_factory(
Event, EventFooterLink,
EventFooterLinkForm,
formset=BaseEventFooterLinkFormSet,
can_order=False, can_delete=True, extra=0
)

View File

@@ -1265,8 +1265,7 @@ class CustomerFilterForm(FilterForm):
orders = {
'email': 'email',
'identifier': 'identifier',
'name': 'name_cached',
'external_identifier': 'external_identifier',
'name_cached': 'name_cached',
}
query = forms.CharField(
label=_('Search query'),
@@ -1310,8 +1309,6 @@ class CustomerFilterForm(FilterForm):
Q(email__icontains=query)
| Q(name_cached__icontains=query)
| Q(identifier__istartswith=query)
| Q(external_identifier__icontains=query)
| Q(notes__icontains=query)
)
if fdata.get('status') == 'active':

View File

@@ -32,7 +32,6 @@
# 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 copy
import os
from decimal import Decimal
from urllib.parse import urlencode
@@ -424,10 +423,9 @@ class ItemCreateForm(I18nModelForm):
if self.cleaned_data.get('has_variations'):
if self.cleaned_data.get('copy_from') and self.cleaned_data.get('copy_from').has_variations:
for variation in self.cleaned_data['copy_from'].variations.all():
v = copy.copy(variation)
v.pk = None
v.item = instance
v.save()
ItemVariation.objects.create(item=instance, value=variation.value, active=variation.active,
position=variation.position, default_price=variation.default_price,
description=variation.description, original_price=variation.original_price)
else:
ItemVariation.objects.create(
item=instance, value=__('Standard')

View File

@@ -39,13 +39,12 @@ from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.forms import inlineformset_factory
from django.forms.utils import ErrorDict
from django.utils.crypto import get_random_string
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django_scopes.forms import SafeModelMultipleChoiceField
from i18nfield.forms import I18nFormField, I18nFormSetMixin, I18nTextarea
from i18nfield.forms import I18nFormField, I18nTextarea
from phonenumber_field.formfields import PhoneNumberField
from pytz import common_timezones
@@ -61,7 +60,6 @@ from pretix.base.models import (
Customer, Device, EventMetaProperty, Gate, GiftCard, Membership,
MembershipType, Organizer, Team,
)
from pretix.base.models.organizer import OrganizerFooterLink
from pretix.base.settings import PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS
from pretix.control.forms import ExtFileField, SplitDateTimeField
from pretix.control.forms.event import (
@@ -609,7 +607,7 @@ class CustomerUpdateForm(forms.ModelForm):
class Meta:
model = Customer
fields = ['is_active', 'external_identifier', 'name_parts', 'email', 'is_verified', 'phone', 'locale', 'notes']
fields = ['is_active', 'name_parts', 'email', 'is_verified', 'phone', 'locale']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -653,7 +651,7 @@ class CustomerCreateForm(CustomerUpdateForm):
class Meta:
model = Customer
fields = ['is_active', 'identifier', 'external_identifier', 'name_parts', 'email', 'is_verified', 'phone', 'locale', 'notes']
fields = ['identifier', 'is_active', 'name_parts', 'email', 'is_verified', 'locale']
class MembershipUpdateForm(forms.ModelForm):
@@ -684,25 +682,3 @@ class MembershipUpdateForm(forms.ModelForm):
titles=self.instance.customer.organizer.settings.name_scheme_titles,
label=_('Attendee name'),
)
class OrganizerFooterLinkForm(I18nModelForm):
class Meta:
model = OrganizerFooterLink
fields = ('label', 'url')
class BaseOrganizerFooterLinkFormSet(I18nFormSetMixin, forms.BaseInlineFormSet):
def __init__(self, *args, **kwargs):
organizer = kwargs.pop('organizer', None)
if organizer:
kwargs['locales'] = organizer.settings.get('locales')
super().__init__(*args, **kwargs)
OrganizerFooterLinkFormset = inlineformset_factory(
Organizer, OrganizerFooterLink,
OrganizerFooterLinkForm,
formset=BaseOrganizerFooterLinkFormSet,
can_order=False, can_delete=True, extra=0
)

View File

@@ -314,7 +314,6 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
'pretix.object.cloned': _('This object has been created by cloning.'),
'pretix.organizer.changed': _('The organizer has been changed.'),
'pretix.organizer.settings': _('The organizer settings have been changed.'),
'pretix.organizer.footerlinks.changed': _('The footer links have been changed.'),
'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.webhook.created': _('The webhook has been created.'),
@@ -366,7 +365,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
'pretix.event.order.payment.changed': _('A new payment {local_id} has been started instead of the previous one.'),
'pretix.event.order.email.sent': _('An unidentified type email has been sent.'),
'pretix.event.order.email.error': _('Sending of an email has failed.'),
'pretix.event.order.email.attachments.skipped': _('The email has been sent without attached tickets since they '
'pretix.event.order.email.attachments.skipped': _('The email has been sent without attachments since they '
'would have been too large to be likely to arrive.'),
'pretix.event.order.email.custom_sent': _('A custom email has been sent.'),
'pretix.event.order.position.email.custom_sent': _('A custom email has been sent to an attendee.'),
@@ -469,7 +468,6 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
'pretix.event.testmode.deactivated': _('The test mode has been disabled.'),
'pretix.event.added': _('The event has been created.'),
'pretix.event.changed': _('The event details have been changed.'),
'pretix.event.footerlinks.changed': _('The footer links have been changed.'),
'pretix.event.question.option.added': _('An answer option has been added to the question.'),
'pretix.event.question.option.deleted': _('An answer option has been removed from the question.'),
'pretix.event.question.option.changed': _('An answer option has been changed.'),

View File

@@ -72,31 +72,5 @@
</dd>
<dt>{% trans "Authorization Code" %}</dt>
<dd>{{ payment_info.payment_data.authorizationCode }}</dd>
{% elif payment_info.payment_type == "izettle_qrc" %}
<dt>{% trans "Payment provider" %}</dt>
<dd>PayPal QRC via Zettle</dd>
<dt>{% trans "Payment reference" %}</dt>
<dd>{{ payment_info.payment_data.reference }}</dd>
<dt>{% trans "Transaction ID" %}</dt>
<dd>{{ payment_info.payment_data.transactionId }}</dd>
{% elif payment_info.payment_type == "adyen_legacy" %}
<dt>{% trans "Payment provider" %}</dt>
<dd>Adyen POS</dd>
<dt>{% trans "Reference" %}</dt>
<dd>{{ payment_info.payment_data.pspReference }}</dd>
<dt>{% trans "Terminal ID" %}</dt>
<dd>{{ payment_info.payment_data.terminalId }}</dd>
<dt>{% trans "Payment method" %}</dt>
<dd>{{ payment_info.payment_data.paymentMethod }} ({{ payment_info.payment_data.cardType }} / {{ payment_info.payment_data.cardScheme }} / {{ payment_info.payment_data.paymentMethodVariant }})</dd>
<dt>{% trans "Card holder" %}</dt>
<dd>{{ payment_info.payment_data.cardHolderName }}</dd>
<dt>{% trans "Card number" %}</dt>
<dd>{{ payment_info.payment_data.cardBin }} **** {{ payment_info.payment_data.cardSummary }}</dd>
<dt>{% trans "Card expiration" %}</dt>
<dd>{{ payment_info.payment_data.expiryMonth }} / {{ payment_info.payment_data.expiryYear }}</dd>
<dt>{% trans "Card Entry Mode" %}</dt>
<dd>{{ payment_info.payment_data.posEntryMode }}</dd>
<dt>{% trans "Result Code" %}</dt>
<dd>{{ payment_info.payment_data.posResultCode }}</dd>
{% endif %}
</dl>

View File

@@ -80,17 +80,13 @@
{% elif c.forced and c.successful %}
<span class="fa fa-fw fa-warning" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Additional entry scan: {{ date }}{% endblocktrans %}"></span>
{% elif c.force_sent %}
<span class="fa fa-fw fa-cloud-upload" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.created|date:'SHORT_DATETIME_FORMAT' %}Offline scan. Upload time: {{ date }}{% endblocktrans %}"></span>
{% elif c.forced and not c.successful %}
<br>
<small class="text-muted">{% trans "Failed in offline mode" %}</small>
{% elif c.auto_checked_in %}
<span class="fa fa-fw fa-magic" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically checked in: {{ date }}{% endblocktrans %}"></span>
{% endif %}
{% if c.forced and not c.successful %}
<br>
<small class="text-muted">{% trans "Failed in offline mode" %}</small>
{% endif %}
</td>
<td>
{% if c.type == "exit" %}<span class="fa fa-fw fa-sign-out"></span>{% endif %}

View File

@@ -71,20 +71,13 @@
</p>
</div>
{% else %}
<form method="post" action="{% url "control:event.orders.checkinlists.bulk_action" event=request.event.slug organizer=request.event.organizer.slug list=checkinlist.pk %}" data-asynctask>
<div class="hidden">
{{ filter_form.as_p }}
<input name="returnquery" type="hidden" value="{{ request.META.QUERY_STRING }}">
</div>
<form method="post" action="">
{% csrf_token %}
<div class="table-responsive">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>
<label aria-label="{% trans "select all rows for batch-operation" %}"
class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
</th>
<th></th>
<th>{% trans "Order code" %} <a href="?{% url_replace request 'ordering' '-code'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'code'%}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "Item" %} <a href="?{% url_replace request 'ordering' '-item'%}"><i class="fa fa-caret-down"></i></a>
@@ -107,19 +100,6 @@
<th>{% trans "Timestamp" %} <a href="?{% url_replace request 'ordering' '-timestamp'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'timestamp'%}"><i class="fa fa-caret-up"></i></a></th>
</tr>
{% if page_obj.paginator.num_pages > 1 %}
<tr class="table-select-all warning hidden">
<td>
<input type="checkbox" name="__ALL" id="__all"
data-results-total="{{ page_obj.paginator.count }}">
</td>
<td colspan="8">
<label for="__all">
{% trans "Select all results on other pages as well" %}
</label>
</td>
</tr>
{% endif %}
</thead>
<tbody>
{% for e in entries %}
@@ -200,16 +180,13 @@
</div>
{% if "can_change_orders" in request.eventpermset %}
<button type="submit" class="btn btn-primary btn-save">
<span class="fa fa-sign-in" aria-hidden="true"></span>
{% trans "Check-In selected attendees" %}
</button>
<button type="submit" class="btn btn-default btn-save" name="checkout" value="true">
<span class="fa fa-sign-out" aria-hidden="true"></span>
{% trans "Check-Out selected attendees" %}
</button>
<button type="submit" class="btn btn-danger btn-save" name="revert" value="true">
<span class="fa fa-trash" aria-hidden="true"></span>
{% trans "Delete all check-ins of selected attendees" %}
<button type="submit" class="btn btn-default btn-save" name="revert" value="true">
{% trans "Revert selected check-ins" %}
</button>
{% endif %}
</form>

View File

@@ -48,14 +48,16 @@
Make sure to always use the latest version of our scanning apps for these options to work.
{% endblocktrans %}
<br>
{% blocktrans trimmed %}
If you make use of these advanced options, we recommend using our Android and Desktop apps.
{% endblocktrans %}
<strong>
{% blocktrans trimmed %}
If you make use of these advanced options, we recommend using our Android and Desktop apps.
Custom check-in rules do not work offline with our iOS scanning app.
{% endblocktrans %}
</strong>
</div>
{% bootstrap_field form.allow_multiple_entries layout="control" %}
{% bootstrap_field form.allow_entry_after_exit layout="control" %}
{% bootstrap_field form.addon_match layout="control" %}
{% bootstrap_field form.exit_all_at layout="control" %}
{% bootstrap_field form.auto_checkin_sales_channels layout="control" %}
{% if form.gates %}

View File

@@ -69,8 +69,7 @@
</label>
<div class="col-md-9">
<div class="checkbox">
<label><input type="checkbox" checked="checked"
disabled="disabled"> {% trans "Ask and require input" %}</label>
<label><input type="checkbox" checked="checked" disabled="disabled"> {% trans "Ask and require input" %}</label>
</div>
</div>
</div>
@@ -82,8 +81,7 @@
</label>
<div class="col-md-9 static-form-row">
<p>
<a href="{% url "control:event.settings.invoice" event=request.event.slug organizer=request.organizer.slug %}#tab-0-1-open"
target="_blank">
<a href="{% url "control:event.settings.invoice" event=request.event.slug organizer=request.organizer.slug %}#tab-0-1-open" target="_blank">
{% trans "See invoice settings" %}
</a>
</p>
@@ -103,8 +101,7 @@
</label>
<div class="col-md-9 static-form-row">
<p>
<a href="{% url "control:event.items.questions" event=request.event.slug organizer=request.organizer.slug %}"
target="_blank">
<a href="{% url "control:event.items.questions" event=request.event.slug organizer=request.organizer.slug %}" target="_blank">
{% trans "Manage questions" %}
</a>
</p>
@@ -235,74 +232,10 @@
{% bootstrap_field sform.display_net_prices layout="control" %}
{% bootstrap_field sform.show_variations_expanded layout="control" %}
{% bootstrap_field sform.hide_sold_out layout="control" %}
<div class="form-group">
<label class="col-md-3 control-label">
{% trans "Footer links" %}<br>
<span class="optional">{% trans "Optional" %}</span>
</label>
<div class="col-md-9">
<p class="help-block">
{% blocktrans trimmed %}
These links will be shown in the footer of your ticket shop. You could
for example link your terms of service here. Your contact address, imprint, and privacy
policy will be linked automatically (if you configured them), so you do not need to add
them here.
{% endblocktrans %}
</p>
<div class="formset" data-formset data-formset-prefix="{{ footer_links_formset.prefix }}">
{{ footer_links_formset.management_form }}
{% bootstrap_formset_errors footer_links_formset %}
<div data-formset-body>
{% for form in footer_links_formset %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="col-md-5">
{% bootstrap_form_errors form %}
{% bootstrap_field form.label layout='inline' form_group_class="" %}
</div>
<div class="col-md-5">
{% bootstrap_field form.url layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ footer_links_formset.empty_form.id }}
{% bootstrap_field footer_links_formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="col-md-5">
{% bootstrap_field footer_links_formset.empty_form.label layout='inline' form_group_class="" %}
</div>
<div class="col-md-5">
{% bootstrap_field footer_links_formset.empty_form.url layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-default" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add link" %}</button>
</p>
</div>
</div>
</div>
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
{% propagated request.event org_url "meta_noindex" %}
{% bootstrap_field sform.meta_noindex layout="control" %}
{% endpropagated %}
{% if sform.frontpage_subevent_ordering %}
{% bootstrap_field sform.frontpage_subevent_ordering layout="control" %}
{% endif %}
@@ -312,11 +245,6 @@
{% if sform.event_list_available_only %}
{% bootstrap_field sform.event_list_available_only layout="control" %}
{% endif %}
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
{% propagated request.event org_url "meta_noindex" %}
{% bootstrap_field sform.meta_noindex layout="control" %}
{% endpropagated %}
</fieldset>
<fieldset>
<legend>{% trans "Cart" %}</legend>
@@ -334,15 +262,13 @@
</div>
<div class="alert alert-info">
{% blocktrans trimmed %}
The waiting list determines availability mainly based on quotas. If you use a seating plan and
your
The waiting list determines availability mainly based on quotas. If you use a seating plan and your
number of available seats is less than the available quota, you might run into situations where
people are sent an email from the waiting list but still are unable to book a seat.
{% endblocktrans %}
<strong>
{% blocktrans trimmed %}
Specifically, this means the waiting list is not safe to use together with the minimum
distance
Specifically, this means the waiting list is not safe to use together with the minimum distance
feature of our seating plan module.
{% endblocktrans %}
</strong>

View File

@@ -10,7 +10,7 @@
<p>{% blocktrans %}You cannot delete the discount <strong>{{ discount }}</strong> because it already has
been used as part of an order.{% endblocktrans %}</p>
<div class="form-group submit-group">
<a href="{% url "control:event.items.discounts" organizer=request.event.organizer.slug event=request.event.slug %}"
<a href="{% url "control:event.discounts" organizer=request.event.organizer.slug event=request.event.slug %}"
class="btn btn-default btn-cancel">
{% trans "Cancel" %}
</a>

View File

@@ -153,7 +153,7 @@
{% endif %}
</td>
<td>
<span class="fa fa-fw fa-{{ o.sales_channel_obj.icon }} text-muted"
<span class="fa fa-{{ o.sales_channel_obj.icon }} text-muted"
data-toggle="tooltip" title="{% trans o.sales_channel_obj.verbose_name %}"></span>
{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}
</td>

View File

@@ -27,10 +27,6 @@
<dl class="dl-horizontal">
<dt>{% trans "Customer ID" %}</dt>
<dd>#{{ customer.identifier }}</dd>
{% if customer.external_identifier %}
<dt>{% trans "External identifier" %}</dt>
<dd>{{ customer.external_identifier }}</dd>
{% endif %}
<dt>{% trans "Status" %}</dt>
<dd>
{% if not customer.is_active %}
@@ -63,10 +59,6 @@
<dt>{% trans "Last login" %}</dt>
<dd>{% if customer.last_login %}{{ customer.last_login|date:"SHORT_DATETIME_FORMAT" }}{% else %}
{% endif %}</dd>
{% if customer.notes %}
<dt>{% trans "Notes" %}</dt>
<dd>{{ customer.notes|linebreaks }}</dd>
{% endif %}
</dl>
</form>
<div class="text-right">

View File

@@ -62,9 +62,6 @@
<th>{% trans "Name" %}
<a href="?{% url_replace request 'ordering' '-name' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'name' %}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "External identifier" %}
<a href="?{% url_replace request 'ordering' '-external_identifier' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'external_identifier' %}"><i class="fa fa-caret-up"></i></a></th>
<th></th>
</tr>
</thead>
@@ -84,7 +81,6 @@
{% if not c.is_verified %}</strike>{% endif %}
</td>
<td>{{ c.name }}</td>
<td>{% if c.external_identifier %}{{ c.external_identifier }}{% endif %}</td>
<td class="text-right">
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=c.identifier %}"
class="btn btn-default btn-sm" data-toggle="tooltip" title="{% trans "Details" %}">

View File

@@ -50,77 +50,6 @@
{% bootstrap_field sform.event_list_availability layout="control" %}
{% bootstrap_field sform.organizer_link_back layout="control" %}
{% bootstrap_field sform.meta_noindex layout="control" %}
<div class="form-group">
<label class="col-md-3 control-label">
{% trans "Footer links" %}<br>
<span class="optional">{% trans "Optional" %}</span>
</label>
<div class="col-md-9">
<p class="help-block">
{% blocktrans trimmed %}
These links will be shown in the footer of your ticket shop. You could
for example link your terms of service here. Your contact address, imprint, and privacy
policy will be linked automatically (if you configured them), so you do not need to add
them here.
{% endblocktrans %}
</p>
<p class="help-block">
{% blocktrans trimmed %}
The links you configure here will also be shown on all of your events.
{% endblocktrans %}
</p>
<div class="formset" data-formset data-formset-prefix="{{ footer_links_formset.prefix }}">
{{ footer_links_formset.management_form }}
{% bootstrap_formset_errors footer_links_formset %}
<div data-formset-body>
{% for form in footer_links_formset %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="col-md-5">
{% bootstrap_form_errors form %}
{% bootstrap_field form.label layout='inline' form_group_class="" %}
</div>
<div class="col-md-5">
{% bootstrap_field form.url layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ footer_links_formset.empty_form.id }}
{% bootstrap_field footer_links_formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="col-md-5">
{% bootstrap_field footer_links_formset.empty_form.label layout='inline' form_group_class="" %}
</div>
<div class="col-md-5">
{% bootstrap_field footer_links_formset.empty_form.url layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-default" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add link" %}</button>
</p>
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>{% trans "Localization" %}</legend>

View File

@@ -16,12 +16,6 @@
</li>
{% endfor %}
</ul>
<div class="alert-info alert">
{% blocktrans trimmed %}
It is possible that some of the above dates can't be deleted if a plugin has data attached to them.
In that case, they will be disabled instead.
{% endblocktrans %}
</div>
{% endif %}
{% if forbidden %}
<p>{% blocktrans trimmed %}The following dates can't be deleted as they already have orders, but
@@ -36,8 +30,7 @@
</ul>
{% endif %}
<div class="form-group submit-group">
<a href="{% url "control:event.subevents" organizer=request.event.organizer.slug event=request.event.slug %}"
class="btn btn-default btn-cancel">
<a href="{% url "control:event.subevents" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default btn-cancel">
{% trans "Cancel" %}
</a>
<button type="submit" class="btn btn-danger btn-save" value="delete_confirm" name="action">

View File

@@ -392,7 +392,6 @@ 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+)/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'),
re_path(r'^checkinlists/(?P<list>\d+)/delete$', checkin.CheckinListDelete.as_view(),

View File

@@ -37,7 +37,7 @@ from django.contrib import messages
from django.db import transaction
from django.db.models import Exists, Max, OuterRef, Prefetch, Subquery
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
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 is_aware, make_aware, now
@@ -49,7 +49,6 @@ 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.signals import checkin_created
from pretix.base.views.tasks import AsyncPostView
from pretix.control.forms.checkin import CheckinListForm
from pretix.control.forms.filter import (
CheckinFilterForm, CheckinListAttendeeFilterForm,
@@ -59,13 +58,11 @@ from pretix.control.views import CreateView, PaginationMixin, UpdateView
from pretix.helpers.models import modelcopy
class CheckInListQueryMixin:
@cached_property
def request_data(self):
if self.request.method == "POST":
return self.request.POST
return self.request.GET
class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
model = Checkin
context_object_name = 'entries'
template_name = 'pretixcontrol/checkin/index.html'
permission = 'can_view_orders'
def get_queryset(self, filter=True):
cqs = Checkin.objects.filter(
@@ -108,28 +105,16 @@ class CheckInListQueryMixin:
if filter and self.filter_form.is_valid():
qs = self.filter_form.filter_qs(qs)
if 'checkin' in self.request_data and '__ALL' not in self.request_data:
qs = qs.filter(
id__in=self.request_data.getlist('checkin')
)
return qs
@cached_property
def filter_form(self):
return CheckinListAttendeeFilterForm(
data=self.request_data,
data=self.request.GET,
event=self.request.event,
list=self.list
)
class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInListQueryMixin, ListView):
model = Checkin
context_object_name = 'entries'
template_name = 'pretixcontrol/checkin/index.html'
permission = 'can_view_orders'
def dispatch(self, request, *args, **kwargs):
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
return super().dispatch(request, *args, **kwargs)
@@ -168,23 +153,18 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInList
e.last_exit_aware = e.last_exit
return ctx
def post(self, request, *args, **kwargs):
if "can_change_orders" not in request.eventpermset:
messages.error(request, _('You do not have permission to perform this action.'))
return redirect(reverse('control:event.orders.checkins', kwargs={
'event': self.request.event.slug,
'organizer': self.request.event.organizer.slug
}) + '?' + request.GET.urlencode())
class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMixin, AsyncPostView):
template_name = 'pretixcontrol/organizers/device_bulk_edit.html'
permission = 'can_change_orders'
context_object_name = 'device'
positions = self.get_queryset(filter=False).filter(
pk__in=request.POST.getlist('checkin')
)
def dispatch(self, request, *args, **kwargs):
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
return super().get_queryset().prefetch_related(None).order_by()
@transaction.atomic()
def async_post(self, request, *args, **kwargs):
self.list = get_object_or_404(request.event.checkin_lists.all(), pk=kwargs.get("list"))
positions = self.get_queryset()
if request.POST.get('revert') == 'true':
for op in positions:
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
@@ -197,11 +177,12 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi
}, user=request.user)
op.order.touch()
return 'reverted', request.POST.get('returnquery')
messages.success(request, _('The selected check-ins have been reverted.'))
else:
t = Checkin.TYPE_EXIT if request.POST.get('checkout') == 'true' else Checkin.TYPE_ENTRY
for op in positions:
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
t = Checkin.TYPE_EXIT if request.POST.get('checkout') == 'true' else Checkin.TYPE_ENTRY
lci = op.checkins.filter(list=self.list).first()
if self.list.allow_multiple_entries or t != Checkin.TYPE_ENTRY or (lci and lci.type != Checkin.TYPE_ENTRY):
ci = Checkin.objects.create(position=op, list=self.list, datetime=now(), type=t)
@@ -225,22 +206,14 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi
'web': True
}, user=request.user)
checkin_created.send(op.order.event, checkin=ci)
return 'checked-out' if t == Checkin.TYPE_EXIT else 'checked-in', request.POST.get('returnquery')
def get_success_message(self, value):
if value[0] == 'reverted':
return _('The selected check-ins have been reverted.')
elif value[0] == 'checked-out':
return _('The selected tickets have been marked as checked out.')
else:
return _('The selected tickets have been marked as checked in.')
messages.success(request, _('The selected tickets have been marked as checked in.'))
def get_success_url(self, value):
return reverse('control:event.orders.checkinlists.show', kwargs={
return redirect(reverse('control:event.orders.checkinlists.show', kwargs={
'event': self.request.event.slug,
'organizer': self.request.event.organizer.slug,
'list': self.list.pk
}) + ('?' + value[1] if value[1] else '')
}) + '?' + request.GET.urlencode())
class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
@@ -429,9 +402,9 @@ class CheckinListView(EventPermissionRequiredMixin, PaginationMixin, ListView):
qs = Checkin.all.filter(
list__event=self.request.event,
).select_related(
'position', 'position__order', 'position__item', 'position__variation', 'position__subevent'
'position', 'position', 'position__item', 'position__variation', 'position__subevent'
).prefetch_related(
'list', 'gate', 'device'
'list', 'gate'
)
if self.filter_form.is_valid():
qs = self.filter_form.filter_qs(qs)

View File

@@ -74,9 +74,9 @@ from pretix.base.signals import register_ticket_outputs
from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.control.forms.event import (
CancelSettingsForm, CommentForm, ConfirmTextFormset, EventDeleteForm,
EventFooterLinkFormset, EventMetaValueForm, EventSettingsForm,
EventUpdateForm, InvoiceSettingsForm, ItemMetaPropertyForm,
MailSettingsForm, PaymentSettingsForm, ProviderForm, QuickSetupForm,
EventMetaValueForm, EventSettingsForm, EventUpdateForm,
InvoiceSettingsForm, ItemMetaPropertyForm, MailSettingsForm,
PaymentSettingsForm, ProviderForm, QuickSetupForm,
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
TicketSettingsForm, WidgetCodeForm,
)
@@ -186,7 +186,6 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
context['meta_forms'] = self.meta_forms
context['item_meta_property_formset'] = self.item_meta_property_formset
context['confirm_texts_formset'] = self.confirm_texts_formset
context['footer_links_formset'] = self.footer_links_formset
return context
@transaction.atomic
@@ -196,7 +195,6 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
self.save_meta()
self.save_item_meta_property_formset(self.object)
self.save_confirm_texts_formset(self.object)
self.save_footer_links_formset(self.object)
change_css = False
if self.sform.has_changed() or self.confirm_texts_formset.has_changed():
@@ -206,10 +204,6 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
self.request.event.log_action('pretix.event.settings', user=self.request.user, data=data)
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
change_css = True
if self.footer_links_formset.has_changed():
self.request.event.log_action('pretix.event.footerlinks.changed', user=self.request.user, data={
'data': self.footer_links_formset.cleaned_data
})
if form.has_changed():
self.request.event.log_action('pretix.event.changed', user=self.request.user, data={
k: (form.cleaned_data.get(k).name
@@ -244,8 +238,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]) and \
self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid() and \
self.footer_links_formset.is_valid():
self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid():
# reset timezone
zone = timezone(self.sform.cleaned_data['timezone'])
event = form.instance
@@ -299,18 +292,10 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
def save_confirm_texts_formset(self, obj):
obj.settings.confirm_texts = LazyI18nStringList(
form_data['text'].data
for form_data in sorted((d for d in self.confirm_texts_formset.cleaned_data if d), key=operator.itemgetter("ORDER"))
if form_data and not form_data.get("DELETE", False)
for form_data in sorted(self.confirm_texts_formset.cleaned_data, key=operator.itemgetter("ORDER"))
if not form_data.get("DELETE", False)
)
@cached_property
def footer_links_formset(self):
return EventFooterLinkFormset(self.request.POST if self.request.method == "POST" else None, event=self.object,
prefix="footer-links", instance=self.object)
def save_footer_links_formset(self, obj):
self.footer_links_formset.save()
class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
model = Event

View File

@@ -92,8 +92,8 @@ from pretix.control.forms.organizer import (
CustomerCreateForm, CustomerUpdateForm, DeviceBulkEditForm, DeviceForm,
EventMetaPropertyForm, GateForm, GiftCardCreateForm, GiftCardUpdateForm,
MailSettingsForm, MembershipTypeForm, MembershipUpdateForm,
OrganizerDeleteForm, OrganizerFooterLinkFormset, OrganizerForm,
OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, WebHookForm,
OrganizerDeleteForm, OrganizerForm, OrganizerSettingsForm,
OrganizerUpdateForm, TeamForm, WebHookForm,
)
from pretix.control.logdisplay import OVERVIEW_BANLIST
from pretix.control.permissions import (
@@ -416,13 +416,11 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
def get_context_data(self, *args, **kwargs) -> dict:
context = super().get_context_data(*args, **kwargs)
context['sform'] = self.sform
context['footer_links_formset'] = self.footer_links_formset
return context
@transaction.atomic
def form_valid(self, form):
self.sform.save()
self.save_footer_links_formset(self.object)
change_css = False
if self.sform.has_changed():
self.request.organizer.log_action(
@@ -437,10 +435,6 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
)
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
change_css = True
if self.footer_links_formset.has_changed():
self.request.organizer.log_action('pretix.organizer.footerlinks.changed', user=self.request.user, data={
'data': self.footer_links_formset.cleaned_data
})
if form.has_changed():
self.request.organizer.log_action(
'pretix.organizer.changed',
@@ -472,19 +466,11 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid() and self.sform.is_valid() and self.footer_links_formset.is_valid():
if form.is_valid() and self.sform.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
@cached_property
def footer_links_formset(self):
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):
self.footer_links_formset.save()
class OrganizerCreate(CreateView):
model = Organizer
@@ -642,25 +628,14 @@ class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
def delete(self, request, *args, **kwargs):
success_url = self.get_success_url()
self.object = self.get_object()
if not self.is_allowed():
messages.error(request, _('The selected team cannot be deleted.'))
return redirect(success_url)
try:
if self.is_allowed():
self.object.log_action('pretix.team.deleted', user=self.request.user)
self.object.delete()
except ProtectedError:
messages.error(
self.request,
_(
'The team could not be deleted as some constraints (e.g. data created by '
'plug-ins) do not allow it.'
)
)
messages.success(request, _('The selected team has been deleted.'))
return redirect(success_url)
else:
messages.error(request, _('The selected team cannot be deleted.'))
return redirect(success_url)
messages.success(request, _('The selected team has been deleted.'))
return redirect(success_url)
class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
@@ -855,7 +830,7 @@ class DeviceQueryMixin:
@cached_property
def filter_form(self):
return DeviceFilterForm(data=self.request_data, request=self.request)
return DeviceFilterForm(data=self.request.GET, request=self.request)
def get_queryset(self):
qs = self.request.organizer.devices.prefetch_related(

View File

@@ -41,7 +41,7 @@ from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.files import File
from django.db import connections, transaction
from django.db.models import Count, F, Prefetch, ProtectedError
from django.db.models import Count, F, Prefetch
from django.db.models.functions import Coalesce, TruncDate, TruncTime
from django.forms import inlineformset_factory
from django.http import Http404, HttpResponse, HttpResponseRedirect
@@ -639,14 +639,12 @@ class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View)
})
elif request.POST.get('action') == 'delete_confirm':
for obj in self.get_queryset():
try:
if not obj.allow_delete():
raise ProtectedError('only deactivate', [obj])
if obj.allow_delete():
CartPosition.objects.filter(addon_to__subevent=obj).delete()
obj.cartposition_set.all().delete()
obj.log_action('pretix.subevent.deleted', user=self.request.user)
obj.delete()
except ProtectedError:
else:
obj.log_action(
'pretix.subevent.changed', user=self.request.user, data={
'active': False

View File

@@ -1,36 +0,0 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from django.template.loaders.app_directories import Loader
from django.template.utils import get_app_template_dirs
class AppLoader(Loader):
def get_dirs(self):
ds = get_app_template_dirs('templates')
ignore_patterns = {
# Ignore templates of plugins we don't actually use as they cause trouble during
# static file compression
'/django_filters/',
'/django_otp/',
}
return [d for d in ds if not any(p in str(d) for p in ignore_patterns)]

View File

@@ -25,7 +25,7 @@ from io import BytesIO
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from PIL import Image, ImageOps, ImageSequence
from PIL import Image, ImageOps
from PIL.Image import Resampling
from pretix.helpers.models import Thumbnail
@@ -171,23 +171,12 @@ def create_thumbnail(sourcename, size):
except:
raise ThumbnailError('Could not load image')
frames = [resize_image(frame, size) for frame in ImageSequence.Iterator(image)]
image_out = frames[0]
save_kwargs = {}
image = resize_image(image, size)
if source.name.lower().endswith('.jpg') or source.name.lower().endswith('.jpeg'):
# Yields better file sizes for photos
target_ext = 'jpeg'
quality = 95
elif source.name.lower().endswith('.gif') or source.name.lower().endswith('.png'):
target_ext = source.name.lower()[-3:]
quality = None
image_out.info = image.info
save_kwargs = {
'append_images': frames[1:],
'loop': image.info.get('loop', 0),
'save_all': True,
}
else:
target_ext = 'png'
quality = None
@@ -195,11 +184,11 @@ def create_thumbnail(sourcename, size):
checksum = hashlib.md5(image.tobytes()).hexdigest()
name = checksum + '.' + size.replace('^', 'c') + '.' + target_ext
buffer = BytesIO()
if image_out.mode == "P" and source.name.lower().endswith('.png'):
image_out = image_out.convert('RGBA')
if image_out.mode not in ("1", "L", "RGB", "RGBA"):
image_out = image_out.convert('RGB')
image_out.save(fp=buffer, format=target_ext.upper(), quality=quality, **save_kwargs)
if image.mode == "P" and source.name.lower().endswith('.png'):
image = image.convert('RGBA')
if image.mode not in ("1", "L", "RGB", "RGBA"):
image = image.convert('RGB')
image.save(fp=buffer, format=target_ext.upper(), quality=quality)
imgfile = ContentFile(buffer.getvalue())
t = Thumbnail.objects.create(source=sourcename, size=size)

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+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/"
@@ -30,123 +30,6 @@ msgstr "طلبات مكتملة"
msgid "Comment:"
msgstr "تعليق:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
#, fuzzy
#| msgid "Yes"
msgid "eps"
msgstr "نعم"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "المتابعة"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "جاري تأكيد الدفع الخاص بك …"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr ""
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -169,6 +52,11 @@ msgstr "جاري الاتصال بStripe …"
msgid "Total"
msgstr "المجموع"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "جاري تأكيد الدفع الخاص بك …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr "جاري الاتصال بالبنك الذي تتعامل معه …"
@@ -242,6 +130,10 @@ msgstr "مستخدم"
msgid "Cancel"
msgstr "قم بالإلغاء"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "المتابعة"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -315,7 +207,7 @@ msgid "close"
msgstr "إغلاق"
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
@@ -324,12 +216,12 @@ msgstr ""
"اخترت."
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr "طلبك قيد الانتظار وستتم معالجته قريبا."
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
@@ -338,36 +230,36 @@ msgstr ""
"وصل طلبك للخادم وننتظر تنفيذه. إذا استغرق الأمر أكثر من دقيقتين تواصل معنا "
"أو عاود المحاولة مجددا."
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr "حدث خطأ من نوع {code}."
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
msgstr "لم نتمكن من الاتصال بالخادم، لكن سنواصل المحاولة، رمز آخر خطأ: {code}"
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr "استغرقت الطلب فترة طويلة، الرجاء المحاولة مرة أخرى."
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
msgstr ""
"لا يمكننا الوصول إلى الخادم حاليا، حاول مرة أخرى من فضلك. رمز الخطأ : {code}"
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "جاري معالجة طلبك …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
@@ -376,7 +268,7 @@ msgstr ""
"نعمل الآن على ارسال طلبك إلى الخادم، إذا أستغرقت العملية أكثر من دقيقة، يرجى "
"التحقق من اتصالك بالإنترنت ثم أعد تحميل الصفحة مرة أخرى."
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr "أغلق الرسالة"
@@ -482,48 +374,48 @@ msgstr "الدقائق"
msgid "Check-in QR"
msgstr "QR الدخول"
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "لا يمكن تحميل ملف PDF الخلفية للأسباب التالية:"
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr "مجموعة من العناصر"
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr "عنصر نص"
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr "منطقة باركود"
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr "منطقة صورة"
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr "مدعوم من pretix"
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr "عنصر"
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "تصميم التذكرة"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr "فشلت عملية الحفظ."
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr "حصل خطأ أثناء رفع ملف PDF الخاص بك، يرجى المحاولة مرة أخرى."
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr "هل تريد أن تغادر المحرر دون حفظ التعديلات؟"
@@ -651,20 +543,20 @@ msgstr "ستسترد %(currency)%(amount)"
msgid "Please enter the amount the organizer can keep."
msgstr "الرجاء إدخال المبلغ الذي يمكن للمنظم الاحتفاظ به."
#: pretix/static/pretixpresale/js/ui/main.js:377
#: pretix/static/pretixpresale/js/ui/main.js:364
msgid "Please enter a quantity for one of the ticket types."
msgstr "الرجاء إدخال عدد لأحد أنواع التذاكر."
#: pretix/static/pretixpresale/js/ui/main.js:413
#: pretix/static/pretixpresale/js/ui/main.js:400
msgid "required"
msgstr "مطلوب"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr "المنطقة الزمنية:"
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr "التوقيت المحلي:"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+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-"
@@ -29,121 +29,6 @@ msgstr ""
msgid "Comment:"
msgstr "Comentari:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
msgid "eps"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr ""
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -166,6 +51,11 @@ msgstr ""
msgid "Total"
msgstr ""
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr ""
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr ""
@@ -239,6 +129,10 @@ msgstr ""
msgid "Cancel"
msgstr ""
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr ""
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -305,61 +199,61 @@ msgid "close"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
"browser and try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "Estem processant la vostra sol·licitud …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
"page and try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr ""
@@ -465,48 +359,48 @@ msgstr ""
msgid "Check-in QR"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "Disseny del tiquet"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
@@ -624,22 +518,22 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:377
#: pretix/static/pretixpresale/js/ui/main.js:364
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:413
#: pretix/static/pretixpresale/js/ui/main.js:400
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Cistella expirada"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+0000\n"
"PO-Revision-Date: 2021-12-06 23:00+0000\n"
"Last-Translator: Ondřej Sokol <osokol@treesoft.cz>\n"
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -29,123 +29,6 @@ msgstr "Označeno jako zaplacené"
msgid "Comment:"
msgstr "Komentář:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
#, fuzzy
#| msgid "Yes"
msgid "eps"
msgstr "Ano"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Pokračovat"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Potvrzuji vaši platbu …"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr ""
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -168,6 +51,11 @@ msgstr "Kontaktuji Stripe …"
msgid "Total"
msgstr "Celkem"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Potvrzuji vaši platbu …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr "Kontaktuji vaši banku …"
@@ -241,6 +129,10 @@ msgstr "Uplatněno"
msgid "Cancel"
msgstr "Zrušit"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Pokračovat"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -307,7 +199,7 @@ msgid "close"
msgstr "zavřít"
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
@@ -316,12 +208,12 @@ msgstr ""
"to může trvat několik minut."
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr "Váš požadavek byl vložem do fronty serveru a brzy bude zpracován."
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
@@ -331,14 +223,14 @@ msgstr ""
"Pokud to trvá více jak dvě minuty, prosím kontaktuje nás nebo se vraťte do "
"vašeho prohlížeče a zkuste to znovu."
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr "Vyskytla se chyba {code}."
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
@@ -346,12 +238,12 @@ msgstr ""
"Momentálně nemůžeme kontaktovat server, ale stále se o to pokoušíme. "
"Poslední chybový kód: {code}"
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr "Zpracování požadavku trvá příliš dlouho. Prosím zkuste to znovu."
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
@@ -359,11 +251,11 @@ msgstr ""
"Momentálně nemůžeme kontaktovat server. Prosím zkuste to znovu. Chybový kód: "
"{code}"
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "Zpracováváme váš požadavek …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
@@ -373,7 +265,7 @@ msgstr ""
"prosím zkontrolujte své internetové připojení a znovu načtěte stránku a "
"zkuste to znovu."
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr "Zavřít zprávu"
@@ -479,48 +371,48 @@ msgstr "minuty"
msgid "Check-in QR"
msgstr "Check-in QR kód"
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "Pozadí PDF nemohl být načten:"
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr "Skupina objektů"
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr "Textový objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr "Oblast s QR kódem"
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr "Oblast obrazu"
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr "Poháněno společností pretix"
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr "Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "Design vstupenky"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr "Uložení se nepodařilo."
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr "Při nahrávání souboru PDF došlo k problému, zkuste to prosím znovu."
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr "Opravdu chcete opustit editor bez uložení změn?"
@@ -644,20 +536,20 @@ msgstr "Dostanete %(currency)s %(amount)s zpět"
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:377
#: pretix/static/pretixpresale/js/ui/main.js:364
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:413
#: pretix/static/pretixpresale/js/ui/main.js:400
msgid "required"
msgstr "povinný"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr "Časové pásmo:"
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr "Místní čas:"

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+0000\n"
"PO-Revision-Date: 2022-04-01 13:36+0000\n"
"Last-Translator: Anna-itk <abc@aarhus.dk>\n"
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -28,126 +28,6 @@ msgstr "Markeret som betalt"
msgid "Comment:"
msgstr "Kommentar:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
#, fuzzy
#| msgid "Yes"
msgid "eps"
msgstr "Ja"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
#, fuzzy
#| msgctxt "widget"
#| msgid "Continue"
msgid "Continue"
msgstr "Fortsæt"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Bekræfter din betaling …"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr ""
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -170,6 +50,11 @@ msgstr "Kontakter Stripe …"
msgid "Total"
msgstr "Total"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Bekræfter din betaling …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr "Kontakter din bank …"
@@ -249,6 +134,13 @@ msgstr "Indløs"
msgid "Cancel"
msgstr ""
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
#, fuzzy
#| msgctxt "widget"
#| msgid "Continue"
msgid "Continue"
msgstr "Fortsæt"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -322,7 +214,7 @@ msgid "close"
msgstr "Luk"
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
#, fuzzy
#| msgid ""
#| "Your request has been queued on the server and will now be processed. "
@@ -335,7 +227,7 @@ msgstr ""
"der gå op til et par minutter."
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
#, fuzzy
#| msgid ""
#| "Your request has been queued on the server and will now be processed. "
@@ -346,7 +238,7 @@ msgstr ""
"der gå op til et par minutter."
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
@@ -355,14 +247,14 @@ msgstr ""
"Din forespørgsel er under behandling. Hvis der går mere end to minutter, så "
"kontakt os eller gå tilbage og prøv igen."
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr "Der er sket en fejl ({code})."
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
@@ -370,14 +262,14 @@ msgstr ""
"Vi kan ikke komme i kontakt med serveren, men prøver igen. Seneste fejlkode: "
"{code}"
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
#, fuzzy
#| msgid "The request took to long. Please try again."
msgid "The request took too long. Please try again."
msgstr "Forespørgselen tog for lang tid. Prøv venligst igen."
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
@@ -385,11 +277,11 @@ msgstr ""
"Vi kan ikke komme i kontakt med serveren. Prøv venligst igen. Fejlkode: "
"{code}"
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "Vi behandler din bestilling …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
@@ -398,7 +290,7 @@ msgstr ""
"Din forespørgsel bliver sendt til serveren. Hvis det tager mere end et "
"minut, så tjek din internetforbindelse, genindlæs siden og prøv igen."
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr "Luk besked"
@@ -507,50 +399,50 @@ msgstr ""
msgid "Check-in QR"
msgstr "Check-in QR"
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "Baggrunds-pdf'en kunne ikke hentes af følgende grund:"
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr "Gruppe af objekter"
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr "Tekstobjekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr "QR-kode-område"
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
#, fuzzy
#| msgid "Barcode area"
msgid "Image area"
msgstr "QR-kode-område"
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr "Drevet af pretix"
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr "Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "Billetdesign"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr "Gem fejlede."
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr "Fejl under upload af pdf. Prøv venligt igen."
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
"Er du sikker på at du vil forlade editoren uden at gemme dine ændringer?"
@@ -679,22 +571,22 @@ msgstr "fra %(currency)s %(price)s"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:377
#: pretix/static/pretixpresale/js/ui/main.js:364
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:413
#: pretix/static/pretixpresale/js/ui/main.js:400
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Kurv udløbet"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr "Tidszone:"
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr "Din lokaltid:"
@@ -1018,8 +910,8 @@ msgstr "December"
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
#~ "ticketing powered by pretix</a>"
#~ msgstr ""
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" "
#~ "rel=\"noopener\">billetsystem drevet af pretix</a>"
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener"
#~ "\">billetsystem drevet af pretix</a>"
#~ msgid ""
#~ "Your request has been queued on the server and will now be processed. If "

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"PO-Revision-Date: 2022-04-28 18:04+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+0000\n"
"PO-Revision-Date: 2021-10-25 15:40+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
"de/>\n"
@@ -17,7 +17,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.12\n"
"X-Generator: Weblate 4.8\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -29,121 +29,6 @@ msgstr "Als bezahlt markiert"
msgid "Comment:"
msgstr "Kommentar:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr "PayPal"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr "Venmo"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr "Apple Pay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr "Itaú"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr "PayPal Kredit"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr "Kreditkarte"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr "PayPal Später Zahlen"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr "iDEAL"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr "SEPA-Lastschrift"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr "Bancontact"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr "giropay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr "SOFORT"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
msgid "eps"
msgstr "eps"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr "MyBank"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr "Przelewy24"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr "Verkkopankki"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr "PayU"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr "BLIK"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr "Trustly"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr "Zimpler"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr "Maxima"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr "OXXO"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr "Boleto"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr "WeChat Pay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr "Mercado Pago"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Fortfahren"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Zahlung wird bestätigt …"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr "Zahlungsmethode nicht verfügbar"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -166,6 +51,11 @@ msgstr "Kontaktiere Stripe …"
msgid "Total"
msgstr "Gesamt"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Zahlung wird bestätigt …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr "Kontaktiere Ihre Bank …"
@@ -239,6 +129,10 @@ msgstr "Eingelöst"
msgid "Cancel"
msgstr "Abbrechen"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Fortfahren"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -305,7 +199,7 @@ msgid "close"
msgstr "schließen"
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
@@ -314,14 +208,14 @@ msgstr ""
"einige Minuten dauern."
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr ""
"Ihre Anfrage befindet sich beim Server in der Warteschlange und wird bald "
"verarbeitet."
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
@@ -332,14 +226,14 @@ msgstr ""
"bitte oder gehen Sie in Ihrem Browser einen Schritt zurück und versuchen es "
"erneut."
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr "Ein Fehler ist aufgetreten. Fehlercode: {code}"
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
@@ -347,12 +241,12 @@ msgstr ""
"Wir können den Server aktuell nicht erreichen, versuchen es aber weiter. "
"Letzter Fehlercode: {code}"
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr "Diese Anfrage hat zu lange gedauert. Bitte erneut versuchen."
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
@@ -360,11 +254,11 @@ msgstr ""
"Wir können den Server aktuell nicht erreichen. Bitte versuchen Sie es noch "
"einmal. Fehlercode: {code}"
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "Wir verarbeiten Ihre Anfrage …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
@@ -374,7 +268,7 @@ msgstr ""
"dauert, prüfen Sie bitte Ihre Internetverbindung. Danach können Sie diese "
"Seite neu laden und es erneut versuchen."
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr "Schließen"
@@ -414,7 +308,7 @@ msgstr "Aktueller Zeitpunkt"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:71
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
msgstr "Aktueller Tag der Woche (1 = Montag, 7 = Sonntag)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:75
msgid "Number of previous entries"
@@ -430,11 +324,11 @@ msgstr "Anzahl an Tagen mit vorherigem Eintritt"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:87
msgid "Minutes since last entry (-1 on first entry)"
msgstr "Minuten seit vorherigem Eintritt (-1 bei erstem Zutritt)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:91
msgid "Minutes since first entry (-1 on first entry)"
msgstr "Minuten seit erstem Eintritt (-1 bei erstem Zutritt)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
msgid "All of the conditions below (AND)"
@@ -480,49 +374,49 @@ msgstr "Minuten"
msgid "Check-in QR"
msgstr "Check-in-QR-Code"
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr "Gruppe von Objekten"
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr "Text-Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr "QR-Code-Bereich"
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr "Bildbereich"
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr "Event-Ticketshop von pretix"
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr "Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "Ticket-Design"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr "Speichern fehlgeschlagen."
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr ""
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
"Möchten Sie den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
@@ -646,20 +540,20 @@ msgstr "Sie erhalten %(currency)s %(amount)s zurück"
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:377
#: pretix/static/pretixpresale/js/ui/main.js:364
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:413
#: pretix/static/pretixpresale/js/ui/main.js:400
msgid "required"
msgstr "verpflichtend"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr "Zeitzone:"
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr "Deine lokale Zeit:"
@@ -757,7 +651,7 @@ msgstr "Ticket-Shop öffnen"
#: pretix/static/pretixpresale/js/widget/widget.js:35
msgctxt "widget"
msgid "The cart could not be created. Please try again later"
msgstr "Der Warenkorb konnte nicht erstellt werden. Bitte erneut versuchen"
msgstr "Der Warenkorb konnte nicht erstellt werden. Bitte erneut versuchen."
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"

View File

@@ -11,7 +11,6 @@ Alipay
and
App
Apps
APM
as
auschecken
Ausgangsscan
@@ -45,13 +44,9 @@ bez
BezahlCode
Bezahlmethode
Blackberry
BLIK
BN
Branding
Browsereinstellungen
BSD
bspw
Boleto
Bundles
bzw
chardet
@@ -89,7 +84,6 @@ email
Enterprise
EPC
EPS
eps
Erstattungsbetrag
Erstattungsliste
Erstattungsmethode
@@ -138,9 +132,7 @@ Installations
integrationen
INV
invalidiert
ISU
iOS
Itaú
iTunes
JavaScript
JSON
@@ -153,12 +145,10 @@ Kosovo
landesspezifische
Lead
Leaflet
Linktext
loszulegen
Ltd
max
MapQuest
Mercado
Merchandise
Meta
Metadaten
@@ -170,7 +160,6 @@ Mo
MOTO
Multibanco
MwSt
MyBank
name
Nr
number
@@ -180,13 +169,10 @@ OpenCage
OpenStreetMap
Opera
Output
OXXO
parsen
Pago
Pay
PayPal
PayPals
PayU
PCI
Platzhalterzeichen
Play
@@ -234,7 +220,6 @@ Scans
Scanergebnis
Scanning
schiefgeht
schiefgelaufen
sechsstelligen
Secret
Security
@@ -277,7 +262,6 @@ TOTP
Trace
Tracking
transaktionale
Trustly
Turnover
txt
überbuchen
@@ -304,7 +288,6 @@ URIs
Ursprüngl
USt
Überweisungs
Venmo
Veranstaltereinstellungen
Veranstalterkonten
Veranstalterkonto
@@ -317,7 +300,6 @@ Veranstaltungs
veranstaltungsweiten
Verfügbarkeitsberechnung
Verfügbarkeitsstatus
Verkkopankki
Veröffentlichbarer
VIP
WebAuthn
@@ -335,10 +317,8 @@ Zahlungsplugins
Zehnerkarten
zeitbasiert
Zeitslotbuchung
Zimpler
zubuchbaren
zurückbuchen
zurückgeleitet
zurückwechseln
zzgl
ZVT

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"PO-Revision-Date: 2022-04-28 18:04+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+0000\n"
"PO-Revision-Date: 2021-10-25 15:40+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
"pretix/pretix-js/de_Informal/>\n"
@@ -17,7 +17,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.12\n"
"X-Generator: Weblate 4.8\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -29,121 +29,6 @@ msgstr "Als bezahlt markiert"
msgid "Comment:"
msgstr "Kommentar:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr "PayPal"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr "Venmo"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr "Apple Pay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr "Itaú"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr "PayPal Kredit"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr "Kreditkarte"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr "PayPal Später Zahlen"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr "iDEAL"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr "SEPA-Lastschrift"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr "Bancontact"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr "giropay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr "SOFORT"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
msgid "eps"
msgstr "eps"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr "MyBank"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr "Przelewy24"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr "Verkkopankki"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr "PayU"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr "BLIK"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr "Trustly"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr "Zimpler"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr "Maxima"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr "OXXO"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr "Boleto"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr "WeChat Pay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr "Mercado Pago"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Fortfahren"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Zahlung wird bestätigt …"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr "Zahlungsmethode nicht verfügbar"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -166,6 +51,11 @@ msgstr "Kontaktiere Stripe …"
msgid "Total"
msgstr "Gesamt"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr "Zahlung wird bestätigt …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr "Kontaktiere deine Bank …"
@@ -239,6 +129,10 @@ msgstr "Eingelöst"
msgid "Cancel"
msgstr "Abbrechen"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr "Fortfahren"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -305,7 +199,7 @@ msgid "close"
msgstr "schließen"
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
@@ -314,14 +208,14 @@ msgstr ""
"dies einige Minuten dauern."
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr ""
"Deine Anfrage befindet sich beim Server in der Warteschlange und wird bald "
"verarbeitet."
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
@@ -331,14 +225,14 @@ msgstr ""
"verarbeitet. Wenn dies länger als zwei Minuten dauert, kontaktiere uns bitte "
"oder gehe in deinem Browser einen Schritt zurück und versuche es erneut."
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr "Ein Fehler vom Typ {code} ist aufgetreten."
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
@@ -346,12 +240,12 @@ msgstr ""
"Wir können den Server aktuell nicht erreichen, versuchen es aber weiter. "
"Letzter Fehlercode: {code}"
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr "Diese Anfrage hat zu lange gedauert. Bitte erneut versuchen."
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
@@ -359,11 +253,11 @@ msgstr ""
"Wir können den Server aktuell nicht erreichen. Bitte versuche es noch "
"einmal. Fehlercode: {code}"
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr "Wir verarbeiten deine Anfrage …"
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
@@ -373,7 +267,7 @@ msgstr ""
"dauert, prüfe bitte deine Internetverbindung. Danach kannst du diese Seite "
"neu laden und es erneut versuchen."
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr "Schließen"
@@ -413,7 +307,7 @@ msgstr "Aktueller Zeitpunkt"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:71
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
msgstr "Aktueller Wochentag (1 = Montag, 7 = Sonntag)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:75
msgid "Number of previous entries"
@@ -429,11 +323,11 @@ msgstr "Anzahl an Tagen mit vorherigem Eintritt"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:87
msgid "Minutes since last entry (-1 on first entry)"
msgstr "Minuten seit vorherigem Zutritt (-1 beim erstem Zutritt)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:91
msgid "Minutes since first entry (-1 on first entry)"
msgstr "Minuten seit erstem Zutritt (-1 bei erstem Zutritt)"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
msgid "All of the conditions below (AND)"
@@ -479,49 +373,49 @@ msgstr "Minuten"
msgid "Check-in QR"
msgstr "Check-in-QR-Code"
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr "Gruppe von Objekten"
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr "Text-Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr "QR-Code-Bereich"
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr "Bildbereich"
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr "Event-Ticketshop von pretix"
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr "Objekt"
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr "Ticket-Design"
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr "Speichern fehlgeschlagen."
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr ""
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
"Möchtest du den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
@@ -645,20 +539,20 @@ msgstr "Du erhältst %(currency)s %(amount)s zurück"
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:377
#: pretix/static/pretixpresale/js/ui/main.js:364
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:413
#: pretix/static/pretixpresale/js/ui/main.js:400
msgid "required"
msgstr "verpflichtend"
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr "Zeitzone:"
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr "Deine lokale Zeit:"

View File

@@ -11,7 +11,6 @@ Alipay
and
App
Apps
APM
as
auschecken
Ausgangsscan
@@ -45,13 +44,9 @@ bez
BezahlCode
Bezahlmethode
Blackberry
BLIK
BN
Branding
Browsereinstellungen
BSD
bspw
Boleto
Bundles
bzw
chardet
@@ -89,7 +84,6 @@ email
Enterprise
EPC
EPS
eps
Erstattungsbetrag
Erstattungsliste
Erstattungsmethode
@@ -138,9 +132,7 @@ Installations
integrationen
INV
invalidiert
ISU
iOS
Itaú
iTunes
JavaScript
JSON
@@ -153,12 +145,10 @@ Kosovo
landesspezifische
Lead
Leaflet
Linktext
loszulegen
Ltd
max
MapQuest
Mercado
Merchandise
Meta
Metadaten
@@ -170,7 +160,6 @@ Mo
MOTO
Multibanco
MwSt
MyBank
name
Nr
number
@@ -180,13 +169,10 @@ OpenCage
OpenStreetMap
Opera
Output
OXXO
parsen
Pago
Pay
PayPal
PayPals
PayU
PCI
Platzhalterzeichen
Play
@@ -234,7 +220,6 @@ Scans
Scanergebnis
Scanning
schiefgeht
schiefgelaufen
sechsstelligen
Secret
Security
@@ -277,7 +262,6 @@ TOTP
Trace
Tracking
transaktionale
Trustly
Turnover
txt
überbuchen
@@ -304,7 +288,6 @@ URIs
Ursprüngl
USt
Überweisungs
Venmo
Veranstaltereinstellungen
Veranstalterkonten
Veranstalterkonto
@@ -317,7 +300,6 @@ Veranstaltungs
veranstaltungsweiten
Verfügbarkeitsberechnung
Verfügbarkeitsstatus
Verkkopankki
Veröffentlichbarer
VIP
WebAuthn
@@ -335,10 +317,8 @@ Zahlungsplugins
Zehnerkarten
zeitbasiert
Zeitslotbuchung
Zimpler
zubuchbaren
zurückbuchen
zurückgeleitet
zurückwechseln
zzgl
ZVT

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-01 07:50+0000\n"
"POT-Creation-Date: 2022-04-27 12:44+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"
@@ -28,121 +28,6 @@ msgstr ""
msgid "Comment:"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
msgid "Apple Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
msgid "Itaú"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
msgid "PayPal Credit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
msgid "Credit Card"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
msgid "PayPal Pay Later"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
msgid "eps"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
msgid "MyBank"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
msgid "PayU"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
msgid "BLIK"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
msgid "Trustly"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
msgid "Zimpler"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
msgid "Maxima"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
msgid "OXXO"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
msgid "Boleto"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:157
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:215
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr ""
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:240
msgid "Payment method unavailable"
msgstr ""
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
@@ -165,6 +50,11 @@ msgstr ""
msgid "Total"
msgstr ""
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:152
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:183
msgid "Confirming your payment …"
msgstr ""
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr ""
@@ -238,6 +128,10 @@ msgstr ""
msgid "Cancel"
msgstr ""
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Continue"
msgstr ""
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
@@ -304,61 +198,61 @@ msgid "close"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:43
#: pretix/static/pretixbase/js/asynctask.js:120
#: pretix/static/pretixbase/js/asynctask.js:119
msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:125
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:131
#: pretix/static/pretixbase/js/asynctask.js:130
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
"browser and try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:90
#: pretix/static/pretixbase/js/asynctask.js:178
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:93
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:145
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:186
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:208
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:216
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
"page and try again."
msgstr ""
#: pretix/static/pretixbase/js/asynctask.js:276
#: pretix/static/pretixbase/js/asynctask.js:270
#: pretix/static/pretixcontrol/js/ui/main.js:71
msgid "Close message"
msgstr ""
@@ -464,48 +358,48 @@ msgstr ""
msgid "Check-in QR"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:382
#: pretix/static/pretixcontrol/js/ui/editor.js:376
msgid "The PDF background file could not be loaded for the following reason:"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:630
#: pretix/static/pretixcontrol/js/ui/editor.js:624
msgid "Group of objects"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:636
#: pretix/static/pretixcontrol/js/ui/editor.js:630
msgid "Text object"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:638
#: pretix/static/pretixcontrol/js/ui/editor.js:632
msgid "Barcode area"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:640
#: pretix/static/pretixcontrol/js/ui/editor.js:634
msgid "Image area"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:642
#: pretix/static/pretixcontrol/js/ui/editor.js:636
msgid "Powered by pretix"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:644
#: pretix/static/pretixcontrol/js/ui/editor.js:638
msgid "Object"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:648
#: pretix/static/pretixcontrol/js/ui/editor.js:642
msgid "Ticket design"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:938
#: pretix/static/pretixcontrol/js/ui/editor.js:932
msgid "Saving failed."
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:988
#: pretix/static/pretixcontrol/js/ui/editor.js:1027
#: pretix/static/pretixcontrol/js/ui/editor.js:982
#: pretix/static/pretixcontrol/js/ui/editor.js:1021
msgid "Error while uploading your PDF file, please try again."
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:1012
#: pretix/static/pretixcontrol/js/ui/editor.js:1006
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
@@ -619,20 +513,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:377
#: pretix/static/pretixpresale/js/ui/main.js:364
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:413
#: pretix/static/pretixpresale/js/ui/main.js:400
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:516
#: pretix/static/pretixpresale/js/ui/main.js:535
#: pretix/static/pretixpresale/js/ui/main.js:503
#: pretix/static/pretixpresale/js/ui/main.js:522
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:526
#: pretix/static/pretixpresale/js/ui/main.js:513
msgid "Your local time:"
msgstr ""

Some files were not shown because too many files have changed in this diff Show More