mirror of
https://github.com/pretix/pretix.git
synced 2026-09-30 19:04:43 +00:00
Compare commits
92
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dac3230930 | ||
|
|
07d27e66d1 | ||
|
|
b404316dfd | ||
|
|
edf97a13cd | ||
|
|
c384bc2e7a | ||
|
|
f16034d0cc | ||
|
|
93469d33e5 | ||
|
|
329b118810 | ||
|
|
748054de56 | ||
|
|
721b179521 | ||
|
|
d3151f978d | ||
|
|
3a25af6496 | ||
|
|
6f1512f200 | ||
|
|
d555b23275 | ||
|
|
375c42dff5 | ||
|
|
21225e7753 | ||
|
|
759ced7268 | ||
|
|
5920419e6b | ||
|
|
7c00383b62 | ||
|
|
4361641857 | ||
|
|
ac8f40353e | ||
|
|
d648c83e4c | ||
|
|
5cd1775e1d | ||
|
|
15d4676f98 | ||
|
|
dfd388ddeb | ||
|
|
8af010e5b7 | ||
|
|
4f4ea01bc0 | ||
|
|
9e4cbcb372 | ||
|
|
07d7264bc6 | ||
|
|
f3b3eba8b3 | ||
|
|
a75dbb5d62 | ||
|
|
254f46d991 | ||
|
|
59d15b0411 | ||
|
|
f0778df911 | ||
|
|
eb4d85c83d | ||
|
|
0fe00fed27 | ||
|
|
7b9d095f4e | ||
|
|
94aec6f511 | ||
|
|
ed25a8b073 | ||
|
|
c9eb936d45 | ||
|
|
7237ece1ca | ||
|
|
18485f5d95 | ||
|
|
909ce5b27d | ||
|
|
c7b82fdc97 | ||
|
|
da380ed75e | ||
|
|
687c7e3ccf | ||
|
|
484b7141d9 | ||
|
|
f60031d67b | ||
|
|
dd29063a84 | ||
|
|
f37dfbd21a | ||
|
|
bb8ef00d49 | ||
|
|
d13c654596 | ||
|
|
2cc73baa99 | ||
|
|
f740d46d47 | ||
|
|
412a5adf8f | ||
|
|
e4da2e5e03 | ||
|
|
9d7038b127 | ||
|
|
ce5af572cc | ||
|
|
6d293e544e | ||
|
|
28a8032adf | ||
|
|
d765a89139 | ||
|
|
3df5b1d075 | ||
|
|
857791445f | ||
|
|
52b28997a2 | ||
|
|
f65a6aa11f | ||
|
|
9faca5ea24 | ||
|
|
867512eee5 | ||
|
|
1436b65347 | ||
|
|
cc06588991 | ||
|
|
32bd9fa265 | ||
|
|
bdc9b155f9 | ||
|
|
1af2941594 | ||
|
|
11dc1e6f70 | ||
|
|
e08243e3b2 | ||
|
|
3a4e30f2ec | ||
|
|
ea2fa741f5 | ||
|
|
20d1bb9d32 | ||
|
|
ad48d592e7 | ||
|
|
4861aca640 | ||
|
|
82450c8250 | ||
|
|
b21b69b2b8 | ||
|
|
80ed6e76cd | ||
|
|
bb211be436 | ||
|
|
3b70ef8c84 | ||
|
|
9d57380c9a | ||
|
|
8b468c31a5 | ||
|
|
9aec608601 | ||
|
|
e542bb606d | ||
|
|
fe1b4ec9d0 | ||
|
|
f04df7a6ee | ||
|
|
1640ddd497 | ||
|
|
27148324a6 |
@@ -1,5 +1,6 @@
|
|||||||
doc/
|
doc/
|
||||||
env/
|
env/
|
||||||
|
node_modules/
|
||||||
res/
|
res/
|
||||||
local/
|
local/
|
||||||
.git/
|
.git/
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[*.{js,jsx,ts,tsx,vue}]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
@@ -46,4 +46,7 @@ jobs:
|
|||||||
- name: Run build
|
- name: Run build
|
||||||
run: python -m build
|
run: python -m build
|
||||||
- name: Check files
|
- name: Check files
|
||||||
run: unzip -l dist/pretix*whl | grep node_modules || exit 1
|
run: |
|
||||||
|
for pat in 'static.dist/vite/widget/widget.js' 'static.dist/vite/control/assets/checkinrules/main-' 'static.dist/vite/control/assets/webcheckin/main-'; do
|
||||||
|
unzip -l dist/pretix*whl | grep -q "$pat" || { echo "Missing: $pat"; exit 1; }
|
||||||
|
done
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: JS Code Style
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- 'src/pretix/static/pretixpresale/widget/**'
|
||||||
|
- 'src/pretix/static/pretixcontrol/js/ui/checkinrules/**'
|
||||||
|
- 'src/pretix/plugins/webcheckin/**'
|
||||||
|
- 'eslint.config.mjs'
|
||||||
|
- 'package.json'
|
||||||
|
- 'package-lock.json'
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- 'src/pretix/static/pretixpresale/widget/**'
|
||||||
|
- 'src/pretix/static/pretixcontrol/js/ui/checkinrules/**'
|
||||||
|
- 'src/pretix/plugins/webcheckin/**'
|
||||||
|
- 'eslint.config.mjs'
|
||||||
|
- 'package.json'
|
||||||
|
- 'package-lock.json'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
eslint:
|
||||||
|
name: eslint
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Node.js 24
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
cache: npm
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run lint:eslint
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
run: make all compress
|
run: make all compress
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./src
|
working-directory: ./src
|
||||||
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test -n 3 -p no:sugar --cov=./ --cov-report=xml tests --maxfail=100
|
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test -n 3 -p no:sugar --cov=./ --cov-report=xml tests --ignore=tests/e2e --maxfail=100
|
||||||
- name: Run concurrency tests
|
- name: Run concurrency tests
|
||||||
working-directory: ./src
|
working-directory: ./src
|
||||||
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test tests/concurrency_tests/ --reuse-db
|
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test tests/concurrency_tests/ --reuse-db
|
||||||
@@ -84,3 +84,46 @@ jobs:
|
|||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
if: matrix.database == 'postgres' && matrix.python-version == '3.13'
|
if: matrix.database == 'postgres' && matrix.python-version == '3.13'
|
||||||
|
e2e:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
name: E2E Tests
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:15
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: pretix
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U postgres -d pretix"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pip
|
||||||
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pip-
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: sudo apt update && sudo apt install -y gettext
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
|
||||||
|
- name: Install JS dependencies
|
||||||
|
working-directory: ./src
|
||||||
|
run: make npminstall
|
||||||
|
- name: Compile
|
||||||
|
working-directory: ./src
|
||||||
|
run: make all compress
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: playwright install
|
||||||
|
- name: Run E2E tests
|
||||||
|
working-directory: ./src
|
||||||
|
run: PRETIX_CONFIG_FILE=tests/ci_postgres.cfg py.test tests/e2e/ -v --maxfail=10
|
||||||
|
|||||||
@@ -24,5 +24,7 @@ local/
|
|||||||
.project
|
.project
|
||||||
.pydevproject
|
.pydevproject
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
.vite/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -10,9 +10,10 @@ tests:
|
|||||||
- cd src
|
- cd src
|
||||||
- python manage.py check
|
- python manage.py check
|
||||||
- make all compress
|
- make all compress
|
||||||
|
- playwright install
|
||||||
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test -n 3 tests --maxfail=100
|
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test -n 3 tests --maxfail=100
|
||||||
except:
|
except:
|
||||||
- pypi
|
- '/^v.*$/'
|
||||||
pypi:
|
pypi:
|
||||||
stage: release
|
stage: release
|
||||||
image:
|
image:
|
||||||
@@ -35,7 +36,7 @@ pypi:
|
|||||||
- twine check dist/*
|
- twine check dist/*
|
||||||
- twine upload dist/*
|
- twine upload dist/*
|
||||||
only:
|
only:
|
||||||
- pypi
|
- '/^v.*$/'
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- src/dist/
|
- src/dist/
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
17
|
24
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
/*
|
||||||
+7
-3
@@ -1,6 +1,7 @@
|
|||||||
FROM python:3.13-trixie
|
FROM python:3.13-trixie
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
|
||||||
|
apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
gettext \
|
gettext \
|
||||||
@@ -21,8 +22,7 @@ RUN apt-get update && \
|
|||||||
libmaxminddb0 \
|
libmaxminddb0 \
|
||||||
libmaxminddb-dev \
|
libmaxminddb-dev \
|
||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
nodejs \
|
nodejs && \
|
||||||
npm && \
|
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/* && \
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
dpkg-reconfigure locales && \
|
dpkg-reconfigure locales && \
|
||||||
@@ -50,6 +50,10 @@ COPY deployment/docker/production_settings.py /pretix/src/production_settings.py
|
|||||||
COPY pyproject.toml /pretix/pyproject.toml
|
COPY pyproject.toml /pretix/pyproject.toml
|
||||||
COPY _build /pretix/_build
|
COPY _build /pretix/_build
|
||||||
COPY src /pretix/src
|
COPY src /pretix/src
|
||||||
|
COPY package.json /pretix/package.json
|
||||||
|
COPY package-lock.json /pretix/package-lock.json
|
||||||
|
COPY tsconfig.json /pretix/tsconfig.json
|
||||||
|
COPY vite.config.ts /pretix/vite.config.ts
|
||||||
|
|
||||||
RUN pip3 install -U \
|
RUN pip3 install -U \
|
||||||
pip \
|
pip \
|
||||||
|
|||||||
@@ -48,3 +48,8 @@ recursive-include src Makefile
|
|||||||
recursive-exclude doc *
|
recursive-exclude doc *
|
||||||
recursive-exclude deployment *
|
recursive-exclude deployment *
|
||||||
recursive-exclude res *
|
recursive-exclude res *
|
||||||
|
|
||||||
|
include package.json
|
||||||
|
include package-lock.json
|
||||||
|
include tsconfig.json
|
||||||
|
include vite.config.ts
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ Cart position endpoints
|
|||||||
* ``attendee_email`` (optional)
|
* ``attendee_email`` (optional)
|
||||||
* ``subevent`` (optional)
|
* ``subevent`` (optional)
|
||||||
* ``expires`` (optional)
|
* ``expires`` (optional)
|
||||||
* ``includes_tax`` (optional, **deprecated**, do not use, will be removed)
|
* ``includes_tax`` (optional, **DEPRECATED**, do not use, will be removed)
|
||||||
* ``sales_channel`` (optional)
|
* ``sales_channel`` (optional)
|
||||||
* ``voucher`` (optional, expect a voucher code)
|
* ``voucher`` (optional, expect a voucher code)
|
||||||
* ``addons`` (optional, expect a list of nested objects of cart positions)
|
* ``addons`` (optional, expect a list of nested objects of cart positions)
|
||||||
|
|||||||
@@ -844,3 +844,187 @@ You can also fetch existing leads (if you are authorized to do so):
|
|||||||
:statuscode 200: No error
|
:statuscode 200: No error
|
||||||
:statuscode 401: Invalid authentication code
|
:statuscode 401: Invalid authentication code
|
||||||
:statuscode 403: Not permitted to access bulk data
|
:statuscode 403: Not permitted to access bulk data
|
||||||
|
|
||||||
|
Retrieving Vouchers
|
||||||
|
"""""""""""""""""""
|
||||||
|
|
||||||
|
Vouchers returned by the App API use a different format than described in :ref:`rest-vouchers`.
|
||||||
|
|
||||||
|
.. rst-class:: rest-resource-table
|
||||||
|
|
||||||
|
===================================== ========================== =======================================================
|
||||||
|
Field Type Description
|
||||||
|
===================================== ========================== =======================================================
|
||||||
|
id integer Internal ID of the voucher
|
||||||
|
code string The voucher code that is required to redeem the voucher
|
||||||
|
max_usages integer The maximum number of times this voucher can be
|
||||||
|
redeemed (default: 1).
|
||||||
|
redeemed integer The number of times this voucher already has been
|
||||||
|
redeemed.
|
||||||
|
valid_until datetime The voucher expiration date (or ``null``).
|
||||||
|
subevent string Name of the date inside an event series this voucher belongs to (or ``null``).
|
||||||
|
tag string A string that is used for grouping vouchers
|
||||||
|
comment string An internal exhibitor comment on the voucher.
|
||||||
|
items list of strings A list of items this voucher is restricted to (or ``null``).
|
||||||
|
price_mode string Determines how this voucher affects product prices.
|
||||||
|
Possible values:
|
||||||
|
|
||||||
|
* ``none`` – No effect on price
|
||||||
|
* ``set`` – The product price is set to the given ``value``
|
||||||
|
* ``subtract`` – The product price is determined by the original price *minus* the given ``value``
|
||||||
|
* ``percent`` – The product price is determined by the original price reduced by the percentage given in ``value``
|
||||||
|
value decimal (string) The value (see ``price_mode``)
|
||||||
|
redemptions list of objects A list of objects, where each object represents an order position that has been purchased using the voucher.
|
||||||
|
Each entry will contains the fields ``attendee_fields``, ``redemption_date`` and ``subevent``.
|
||||||
|
|
||||||
|
The attendee data in the ``attendee_fields`` that is shown is based on the event's configuration, and each entry
|
||||||
|
contains the fields ``id``, ``label``, ``value``, and ``details``. ``details`` is usually empty
|
||||||
|
except in a few cases where it contains an additional list of objects
|
||||||
|
with ``value`` and ``label`` keys (e.g. splitting of names).
|
||||||
|
===================================== ========================== =======================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. http:get:: /exhibitors/api/v1/vouchers/
|
||||||
|
|
||||||
|
Returns a list of all vouchers connected to the exhibitor.
|
||||||
|
|
||||||
|
Note that the ``attendee_fields`` array can contain any number of dynamic keys!
|
||||||
|
Depending on the exhibitors permission and event configuration this might be empty, or contain lots of details.
|
||||||
|
The app should dynamically show these values (read-only) with the labels sent by the server.
|
||||||
|
|
||||||
|
|
||||||
|
**Example request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
GET /exhibitors/api/v1/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,
|
||||||
|
"subevent": null,
|
||||||
|
"tag": "testvoucher",
|
||||||
|
"comment": "",
|
||||||
|
"items": [
|
||||||
|
"All"
|
||||||
|
],
|
||||||
|
"price_mode": "set",
|
||||||
|
"value": "12.00",
|
||||||
|
"redemptions": [
|
||||||
|
{
|
||||||
|
"attendee_fields": [
|
||||||
|
{
|
||||||
|
"id": "attendee_name",
|
||||||
|
"label": "Name",
|
||||||
|
"value": "Jon Doe",
|
||||||
|
"details": [
|
||||||
|
{"label": "Given name", "value": "John"},
|
||||||
|
{"label": "Family name", "value": "Doe"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "attendee_email",
|
||||||
|
"label": "Email",
|
||||||
|
"value": "test@example.com",
|
||||||
|
"details": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redemption_date": "2026-05-06",
|
||||||
|
"subevent": null
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
:statuscode 200: No error
|
||||||
|
:statuscode 401: Invalid authentication code
|
||||||
|
:statuscode 403: Not permitted to access bulk data
|
||||||
|
|
||||||
|
.. http:get:: /exhibitors/api/v1/vouchers/(id)/
|
||||||
|
|
||||||
|
Returns the details of a single, specific voucher connected to the exhibitor.
|
||||||
|
|
||||||
|
Note that the ``attendee_fields`` array can contain any number of dynamic keys!
|
||||||
|
Depending on the exhibitors permission and event configuration this might be empty, or contain lots of details.
|
||||||
|
The app should dynamically show these values (read-only) with the labels sent by the server.
|
||||||
|
|
||||||
|
|
||||||
|
**Example request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
GET /exhibitors/api/v1/vouchers/1/ 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
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"code": "43K6LKM37FBVR2YG",
|
||||||
|
"max_usages": 1,
|
||||||
|
"redeemed": 0,
|
||||||
|
"valid_until": null,
|
||||||
|
"subevent": null,
|
||||||
|
"tag": "testvoucher",
|
||||||
|
"comment": "",
|
||||||
|
"items": [
|
||||||
|
"All"
|
||||||
|
],
|
||||||
|
"price_mode": "set",
|
||||||
|
"value": "12.00",
|
||||||
|
"redemptions": [
|
||||||
|
{
|
||||||
|
"attendee_fields": [
|
||||||
|
{
|
||||||
|
"id": "attendee_name",
|
||||||
|
"label": "Name",
|
||||||
|
"value": "Jon Doe",
|
||||||
|
"details": [
|
||||||
|
{"label": "Given name", "value": "John"},
|
||||||
|
{"label": "Family name", "value": "Doe"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "attendee_email",
|
||||||
|
"label": "Email",
|
||||||
|
"value": "test@example.com",
|
||||||
|
"details": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redemption_date": "2026-05-06",
|
||||||
|
"subevent": null
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
:param id: The ``id`` field of the voucher to fetch
|
||||||
|
:statuscode 200: No error
|
||||||
|
:statuscode 401: Invalid authentication code
|
||||||
|
:statuscode 403: Not permitted to access bulk data
|
||||||
|
:statuscode 404: Voucher not found in system
|
||||||
@@ -1070,6 +1070,7 @@ Creating orders
|
|||||||
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
||||||
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
|
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
|
||||||
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
|
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
|
||||||
|
* ``add_to_reusable_medium`` (optional, causes the new ticket to be added to the given reusable medium, identified by its ID)
|
||||||
* ``discount`` (optional, only possible if ``price`` is set; attention: if this is set to not-``null`` on any position, automatic calculation of discounts will not run)
|
* ``discount`` (optional, only possible if ``price`` is set; attention: if this is set to not-``null`` on any position, automatic calculation of discounts will not run)
|
||||||
* ``answers``
|
* ``answers``
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,16 @@ id integer Internal ID of
|
|||||||
type string Type of medium, e.g. ``"barcode"``, ``"nfc_uid"`` or ``"nfc_mf0aes"``.
|
type string Type of medium, e.g. ``"barcode"``, ``"nfc_uid"`` or ``"nfc_mf0aes"``.
|
||||||
organizer string Organizer slug of the organizer who "owns" this medium.
|
organizer string Organizer slug of the organizer who "owns" this medium.
|
||||||
identifier string Unique identifier of the medium. The format depends on the ``type``.
|
identifier string Unique identifier of the medium. The format depends on the ``type``.
|
||||||
|
claim_token string Secret token to claim ownership of the medium (or ``null``)
|
||||||
|
label string Label to identify the medium, usually something human readable (or ``null``)
|
||||||
active boolean Whether this medium may be used.
|
active boolean Whether this medium may be used.
|
||||||
created datetime Date of creation
|
created datetime Date of creation
|
||||||
updated datetime Date of last modification
|
updated datetime Date of last modification
|
||||||
expires datetime Expiry date (or ``null``)
|
expires datetime Expiry date (or ``null``)
|
||||||
customer string Identifier of a customer account this medium belongs to.
|
customer string Identifier of a customer account this medium belongs to.
|
||||||
linked_orderposition integer Internal ID of a ticket this medium is linked to.
|
linked_orderpositions list of integers Internal IDs of tickets this medium is linked to.
|
||||||
|
linked_orderposition integer **DEPRECATED.** ID of the ticket the medium is linked to, if it is linked to
|
||||||
|
only one ticket. ``null``, if the medium is linked to none or multiple tickets.
|
||||||
linked_giftcard integer Internal ID of a gift card this medium is linked to.
|
linked_giftcard integer Internal ID of a gift card this medium is linked to.
|
||||||
info object Additional data, content depends on the ``type``. Consider
|
info object Additional data, content depends on the ``type``. Consider
|
||||||
this internal to the system and don't use it for your own data.
|
this internal to the system and don't use it for your own data.
|
||||||
@@ -39,6 +43,14 @@ Existing media types are:
|
|||||||
- ``nfc_uid``
|
- ``nfc_uid``
|
||||||
- ``nfc_mf0aes``
|
- ``nfc_mf0aes``
|
||||||
|
|
||||||
|
|
||||||
|
.. versionchanged:: 2026.5
|
||||||
|
|
||||||
|
The ``claim_token``, ``label``, ``linked_orderpositions`` attributes have been added, the ``linked_orderposition`` attribute has been
|
||||||
|
deprecated. Note: To maintain backwards compatibility ``linked_orderposition`` contains the internal ID of the linked order position
|
||||||
|
if the medium has exactly one order position in ``linked_orderpositions``.
|
||||||
|
|
||||||
|
|
||||||
Endpoints
|
Endpoints
|
||||||
---------
|
---------
|
||||||
|
|
||||||
@@ -77,6 +89,7 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
|
"linked_orderpositions": [],
|
||||||
"linked_orderposition": None,
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
@@ -92,10 +105,13 @@ Endpoints
|
|||||||
:query string customer: Only show media linked to the given customer.
|
:query string customer: Only show media linked to the given customer.
|
||||||
:query string created_since: Only show media created since a given date.
|
:query string created_since: Only show media created since a given date.
|
||||||
:query string updated_since: Only show media updated since a given date.
|
:query string updated_since: Only show media updated since a given date.
|
||||||
|
:query integer linked_orderpositions: Only show media linked to the given tickets. Note: you can pass multiple ticket IDs by passing
|
||||||
|
``linked_orderpositions`` multiple times. Any medium matching any linked orderposition will be returned.
|
||||||
:query integer linked_orderposition: Only show media linked to the given ticket.
|
:query integer linked_orderposition: Only show media linked to the given ticket.
|
||||||
:query integer linked_giftcard: Only show media linked to the given gift card.
|
:query integer linked_giftcard: Only show media linked to the given gift card.
|
||||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_giftcard.owner_ticket"``, ``"linked_orderposition"``,
|
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_giftcard.owner_ticket"``, ``"linked_orderpositions"``,
|
||||||
or ``"customer"``, the respective field will be shown as a nested value instead of just an ID.
|
``"linked_orderposition"`` (**DEPRECATED**), or ``"customer"``, the respective field will be shown
|
||||||
|
as a nested value instead of just an ID.
|
||||||
The nested objects are identical to the respective resources, except that order positions
|
The nested objects are identical to the respective resources, except that order positions
|
||||||
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
|
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
|
||||||
matching easier. The parameter can be given multiple times.
|
matching easier. The parameter can be given multiple times.
|
||||||
@@ -134,6 +150,7 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
|
"linked_orderpositions": [],
|
||||||
"linked_orderposition": None,
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
@@ -191,6 +208,7 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
|
"linked_orderpositions": [],
|
||||||
"linked_orderposition": None,
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
@@ -198,9 +216,9 @@ Endpoints
|
|||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to look up a medium for
|
:param organizer: The ``slug`` field of the organizer to look up a medium for
|
||||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderpositions"``, or ``"customer"``, the respective
|
||||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
the respective resources, except that the ``linked_orderpositions`` each will have an attribute of the
|
||||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||||
can be given multiple times.
|
can be given multiple times.
|
||||||
:statuscode 201: no error
|
:statuscode 201: no error
|
||||||
@@ -227,6 +245,7 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
|
"linked_orderpositions": [],
|
||||||
"linked_orderposition": None,
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
@@ -251,6 +270,7 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
|
"linked_orderpositions": [],
|
||||||
"linked_orderposition": None,
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
@@ -258,7 +278,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to create a medium for
|
:param organizer: The ``slug`` field of the organizer to create a medium for
|
||||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderpositions"``, or ``"customer"``, the respective
|
||||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||||
@@ -287,7 +307,7 @@ Endpoints
|
|||||||
Content-Length: 94
|
Content-Length: 94
|
||||||
|
|
||||||
{
|
{
|
||||||
"linked_orderposition": 13
|
"linked_orderpositions": [13, 29]
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
@@ -308,7 +328,8 @@ Endpoints
|
|||||||
"active": True,
|
"active": True,
|
||||||
"expires": None,
|
"expires": None,
|
||||||
"customer": None,
|
"customer": None,
|
||||||
"linked_orderposition": 13,
|
"linked_orderpositions": [13, 29],
|
||||||
|
"linked_orderposition": None,
|
||||||
"linked_giftcard": None,
|
"linked_giftcard": None,
|
||||||
"notes": None,
|
"notes": None,
|
||||||
"info": {}
|
"info": {}
|
||||||
@@ -316,7 +337,7 @@ Endpoints
|
|||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to modify
|
:param organizer: The ``slug`` field of the organizer to modify
|
||||||
:param id: The ``id`` field of the medium to modify
|
:param id: The ``id`` field of the medium to modify
|
||||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderpositions"``, or ``"customer"``, the respective
|
||||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ The following values for ``action_types`` are valid with pretix core:
|
|||||||
* ``pretix.subevent.changed``
|
* ``pretix.subevent.changed``
|
||||||
* ``pretix.subevent.deleted``
|
* ``pretix.subevent.deleted``
|
||||||
* ``pretix.event.item.*``
|
* ``pretix.event.item.*``
|
||||||
|
* ``pretix.event.quota.*``
|
||||||
* ``pretix.event.live.activated``
|
* ``pretix.event.live.activated``
|
||||||
* ``pretix.event.live.deactivated``
|
* ``pretix.event.live.deactivated``
|
||||||
* ``pretix.event.testmode.activated``
|
* ``pretix.event.testmode.activated``
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ Backend
|
|||||||
|
|
||||||
.. automodule:: pretix.control.signals
|
.. automodule:: pretix.control.signals
|
||||||
:members: nav_event, html_head, html_page_start, quota_detail_html, nav_topbar, nav_global, nav_organizer, nav_event_settings,
|
:members: nav_event, html_head, html_page_start, quota_detail_html, nav_topbar, nav_global, nav_organizer, nav_event_settings,
|
||||||
order_info, event_settings_widget, oauth_application_registered, order_position_buttons, subevent_forms,
|
order_info, order_approve_info, event_settings_widget, oauth_application_registered,
|
||||||
item_formsets, order_search_filter_q, order_search_forms
|
order_position_buttons, subevent_forms, item_formsets, order_search_filter_q, order_search_forms, subevent_detail_html
|
||||||
|
|
||||||
.. automodule:: pretix.base.signals
|
.. automodule:: pretix.base.signals
|
||||||
:no-index:
|
:no-index:
|
||||||
|
|||||||
@@ -110,6 +110,56 @@ process::
|
|||||||
|
|
||||||
However, beware that code changes will not auto-reload within Celery.
|
However, beware that code changes will not auto-reload within Celery.
|
||||||
|
|
||||||
|
Running the local development server will also automatically start a vite dev server for all control vue components.
|
||||||
|
|
||||||
|
Run the widget development server
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
To locally develop the presale widget you need to start a separate vite dev server using::
|
||||||
|
|
||||||
|
npm run dev:widget
|
||||||
|
|
||||||
|
You can control the org, event and much more via query parameters like this::
|
||||||
|
|
||||||
|
http://localhost:5180/?org=testorg&event=testevent
|
||||||
|
|
||||||
|
The following query parameters are supported:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: 20 20 60
|
||||||
|
|
||||||
|
* - Parameter
|
||||||
|
- Default
|
||||||
|
- Description
|
||||||
|
* - ``org``
|
||||||
|
- ``testorg``
|
||||||
|
- Organization slug
|
||||||
|
* - ``event``
|
||||||
|
- ``testevent``
|
||||||
|
- Event slug
|
||||||
|
* - ``host``
|
||||||
|
- ``http://localhost:8000``
|
||||||
|
- Backend host URL
|
||||||
|
* - ``type``
|
||||||
|
- ``widget``
|
||||||
|
- Element type: ``widget`` or ``button``
|
||||||
|
* - ``mode``
|
||||||
|
- ``dev``
|
||||||
|
- ``dev`` loads the Vite dev source, ``prod`` loads the built ``v2.{lang}.js``
|
||||||
|
* - ``lang``
|
||||||
|
- ``de``
|
||||||
|
- Language code for the prod script
|
||||||
|
* - ``button-text``
|
||||||
|
- ``Buy tickets!``
|
||||||
|
- Text content for the button (only used when ``type=button``)
|
||||||
|
|
||||||
|
Any other query parameter is passed through as an attribute on the widget/button element.
|
||||||
|
For example, ``?skip-ssl-check&list-type=calendar&items=123`` adds those attributes directly.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _`checksandtests`:
|
.. _`checksandtests`:
|
||||||
|
|
||||||
Code checks and unit tests
|
Code checks and unit tests
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
import globals from 'globals'
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import ts from 'typescript-eslint'
|
||||||
|
import stylistic from '@stylistic/eslint-plugin'
|
||||||
|
import vue from 'eslint-plugin-vue'
|
||||||
|
import vuePug from 'eslint-plugin-vue-pug'
|
||||||
|
|
||||||
|
const ignores = globalIgnores([
|
||||||
|
'**/node_modules',
|
||||||
|
'**/dist'
|
||||||
|
])
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
ignores,
|
||||||
|
...ts.config(
|
||||||
|
js.configs.recommended,
|
||||||
|
ts.configs.recommended
|
||||||
|
),
|
||||||
|
stylistic.configs.customize({
|
||||||
|
indent: 'tab',
|
||||||
|
braceStyle: '1tbs',
|
||||||
|
quoteProps: 'as-needed'
|
||||||
|
}),
|
||||||
|
...vue.configs['flat/recommended'],
|
||||||
|
...vuePug.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
localStorage: false,
|
||||||
|
$: 'readonly',
|
||||||
|
$$: 'readonly',
|
||||||
|
$ref: 'readonly',
|
||||||
|
$computed: 'readonly',
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@typescript-eslint/parser'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'no-debugger': 'off',
|
||||||
|
curly: 0,
|
||||||
|
'no-return-assign': 0,
|
||||||
|
'no-console': 'off',
|
||||||
|
'vue/require-default-prop': 0,
|
||||||
|
'vue/require-v-for-key': 0,
|
||||||
|
'vue/valid-v-for': 'warn',
|
||||||
|
'vue/no-reserved-keys': 0,
|
||||||
|
'vue/no-setup-props-destructure': 0,
|
||||||
|
'vue/multi-word-component-names': 0,
|
||||||
|
'vue/max-attributes-per-line': 0,
|
||||||
|
'vue/attribute-hyphenation': ['warn', 'never'],
|
||||||
|
'vue/v-on-event-hyphenation': ['warn', 'never'],
|
||||||
|
'import/first': 0,
|
||||||
|
'@typescript-eslint/ban-ts-comment': 0,
|
||||||
|
'@typescript-eslint/no-explicit-any': 0,
|
||||||
|
'no-use-before-define': 'off',
|
||||||
|
'no-var': 'error',
|
||||||
|
|
||||||
|
'@typescript-eslint/no-use-before-define': ['error', {
|
||||||
|
typedefs: false,
|
||||||
|
functions: false,
|
||||||
|
}],
|
||||||
|
|
||||||
|
'@typescript-eslint/no-unused-vars': ['error', {
|
||||||
|
args: 'all',
|
||||||
|
argsIgnorePattern: '^_',
|
||||||
|
caughtErrors: 'all',
|
||||||
|
caughtErrorsIgnorePattern: '^_',
|
||||||
|
destructuredArrayIgnorePattern: '^_',
|
||||||
|
varsIgnorePattern: '^_',
|
||||||
|
ignoreRestSiblings: true
|
||||||
|
}],
|
||||||
|
|
||||||
|
'@stylistic/comma-dangle': 0,
|
||||||
|
'@stylistic/space-before-function-paren': ['error', 'always'],
|
||||||
|
'@stylistic/max-statements-per-line': ['error', { max: 1, ignoredNodes: ['BreakStatement'] }],
|
||||||
|
'@stylistic/member-delimiter-style': 0,
|
||||||
|
'@stylistic/arrow-parens': 0,
|
||||||
|
'@stylistic/generator-star-spacing': 0,
|
||||||
|
'@stylistic/yield-star-spacing': ['error', 'after'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'src/pretix/static/pretixcontrol/js/ui/checkinrules/**/*.vue',
|
||||||
|
'src/pretix/plugins/webcheckin/**/*.vue',
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
moment: 'readonly',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'src/pretix/static/pretixpresale/widget/**/*.{ts,vue}',
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
LANG: 'readonly',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
Generated
+4781
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "pretix",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"homepage": "https://github.com/pretix/pretix#readme",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/pretix/pretix/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/pretix/pretix.git"
|
||||||
|
},
|
||||||
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.js",
|
||||||
|
"directories": {
|
||||||
|
"doc": "doc"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev:control": "vite",
|
||||||
|
"dev:widget": "vite src/pretix/static/pretixpresale/widget",
|
||||||
|
"build": "npm run build:control -s && npm run build:widget -s",
|
||||||
|
"build:control": "vite build",
|
||||||
|
"build:widget": "vite build src/pretix/static/pretixpresale/widget",
|
||||||
|
"lint:eslint": "eslint src/pretix/static/pretixpresale/widget src/pretix/static/pretixcontrol/js/ui/checkinrules src/pretix/plugins/webcheckin",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.5.30"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^10.0.1",
|
||||||
|
"@stylistic/eslint-plugin": "^5.10.0",
|
||||||
|
"@types/jquery": "^3.5.33",
|
||||||
|
"@types/moment": "^2.11.29",
|
||||||
|
"@types/node": "^25.5.0",
|
||||||
|
"@vitejs/plugin-vue": "^6.0.5",
|
||||||
|
"@vue/eslint-config-typescript": "^14.7.0",
|
||||||
|
"@vue/language-plugin-pug": "^3.2.5",
|
||||||
|
"eslint": "^10.0.3",
|
||||||
|
"eslint-plugin-vue": "^10.8.0",
|
||||||
|
"eslint-plugin-vue-pug": "^1.0.0-alpha.5",
|
||||||
|
"globals": "^17.4.0",
|
||||||
|
"pug": "^3.0.3",
|
||||||
|
"sass-embedded": "^1.98.0",
|
||||||
|
"smol-toml": "^1.6.1",
|
||||||
|
"stylus": "^0.64.0",
|
||||||
|
"typescript-eslint": "^8.57.0",
|
||||||
|
"vite": "^8.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-12
@@ -27,13 +27,13 @@ classifiers = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arabic-reshaper==3.0.0", # Support for Arabic in reportlab
|
"arabic-reshaper==3.0.1", # Support for Arabic in reportlab
|
||||||
"babel",
|
"babel",
|
||||||
"BeautifulSoup4==4.14.*",
|
"BeautifulSoup4==4.14.*",
|
||||||
"bleach==6.3.*",
|
"bleach==6.4.*",
|
||||||
"celery==5.6.*",
|
"celery==5.6.*",
|
||||||
"chardet==5.2.*",
|
"chardet==5.2.*",
|
||||||
"cryptography>=47.0.0",
|
"cryptography>=48.0.0",
|
||||||
"css-inline==0.20.*",
|
"css-inline==0.20.*",
|
||||||
"defusedcsv>=3.0.0",
|
"defusedcsv>=3.0.0",
|
||||||
"dnspython==2.*",
|
"dnspython==2.*",
|
||||||
@@ -43,7 +43,7 @@ dependencies = [
|
|||||||
"django-countries==8.2.*",
|
"django-countries==8.2.*",
|
||||||
"django-filter==25.1",
|
"django-filter==25.1",
|
||||||
"django-formset-js-improved==0.5.0.5",
|
"django-formset-js-improved==0.5.0.5",
|
||||||
"django-formtools==2.5.1",
|
"django-formtools==2.6.1",
|
||||||
"django-hierarkey==2.0.*,>=2.0.1",
|
"django-hierarkey==2.0.*,>=2.0.1",
|
||||||
"django-hijack==3.7.*",
|
"django-hijack==3.7.*",
|
||||||
"django-i18nfield==1.11.*",
|
"django-i18nfield==1.11.*",
|
||||||
@@ -56,7 +56,7 @@ dependencies = [
|
|||||||
"django-redis==6.0.*",
|
"django-redis==6.0.*",
|
||||||
"django-scopes==2.0.*",
|
"django-scopes==2.0.*",
|
||||||
"django-statici18n==2.7.*",
|
"django-statici18n==2.7.*",
|
||||||
"djangorestframework==3.16.*",
|
"djangorestframework==3.17.*",
|
||||||
"dnspython==2.8.*",
|
"dnspython==2.8.*",
|
||||||
"drf_ujson2==1.7.*",
|
"drf_ujson2==1.7.*",
|
||||||
"geoip2==5.*",
|
"geoip2==5.*",
|
||||||
@@ -74,11 +74,11 @@ dependencies = [
|
|||||||
"packaging",
|
"packaging",
|
||||||
"paypalrestsdk==1.13.*",
|
"paypalrestsdk==1.13.*",
|
||||||
"paypal-checkout-serversdk==1.0.*",
|
"paypal-checkout-serversdk==1.0.*",
|
||||||
"PyJWT==2.12.*",
|
"PyJWT==2.13.*",
|
||||||
"phonenumberslite==9.0.*",
|
"phonenumberslite==9.0.*",
|
||||||
"Pillow==12.2.*",
|
"Pillow==12.2.*",
|
||||||
"pretix-plugin-build",
|
"pretix-plugin-build",
|
||||||
"protobuf==7.34.*",
|
"protobuf==7.35.*",
|
||||||
"psycopg2-binary",
|
"psycopg2-binary",
|
||||||
"pycountry",
|
"pycountry",
|
||||||
"pycparser==3.0",
|
"pycparser==3.0",
|
||||||
@@ -91,9 +91,9 @@ dependencies = [
|
|||||||
"pyuca",
|
"pyuca",
|
||||||
"qrcode==8.2",
|
"qrcode==8.2",
|
||||||
"redis==7.4.*",
|
"redis==7.4.*",
|
||||||
"reportlab==4.4.*",
|
"reportlab==4.5.*",
|
||||||
"requests==2.32.*",
|
"requests==2.32.*",
|
||||||
"sentry-sdk==2.58.*",
|
"sentry-sdk==2.61.*",
|
||||||
"sepaxml==2.7.*",
|
"sepaxml==2.7.*",
|
||||||
"stripe==7.9.*",
|
"stripe==7.9.*",
|
||||||
"text-unidecode==1.*",
|
"text-unidecode==1.*",
|
||||||
@@ -108,23 +108,25 @@ dependencies = [
|
|||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
memcached = ["pylibmc"]
|
memcached = ["pylibmc"]
|
||||||
dev = [
|
dev = [
|
||||||
"aiohttp==3.13.*",
|
"aiohttp==3.14.*",
|
||||||
"coverage",
|
"coverage",
|
||||||
"coveralls",
|
"coveralls",
|
||||||
"fakeredis==2.34.*",
|
"fakeredis==2.36.*",
|
||||||
"flake8==7.3.*",
|
"flake8==7.3.*",
|
||||||
"freezegun",
|
"freezegun",
|
||||||
"isort==8.0.*",
|
"isort==8.0.*",
|
||||||
"pep8-naming==0.15.*",
|
"pep8-naming==0.15.*",
|
||||||
"potypo",
|
"potypo",
|
||||||
"pytest-asyncio>=1.3.0",
|
"pytest-asyncio>=1.4.0",
|
||||||
"pytest-cache",
|
"pytest-cache",
|
||||||
"pytest-cov",
|
"pytest-cov",
|
||||||
"pytest-django==4.*",
|
"pytest-django==4.*",
|
||||||
"pytest-mock==3.15.*",
|
"pytest-mock==3.15.*",
|
||||||
"pytest-sugar",
|
"pytest-sugar",
|
||||||
"pytest-xdist==3.8.*",
|
"pytest-xdist==3.8.*",
|
||||||
|
"pytest-playwright",
|
||||||
"pytest==9.0.*",
|
"pytest==9.0.*",
|
||||||
|
"playwright",
|
||||||
"responses",
|
"responses",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,9 @@ ignore =
|
|||||||
CONTRIBUTING.md
|
CONTRIBUTING.md
|
||||||
Dockerfile
|
Dockerfile
|
||||||
SECURITY.md
|
SECURITY.md
|
||||||
|
eslint.config.mjs
|
||||||
|
package-lock.json
|
||||||
|
package.json
|
||||||
|
tsconfig.json
|
||||||
|
vite.config.js
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -9,10 +9,10 @@ localegen:
|
|||||||
./manage.py makemessages --keep-pot --ignore "pretix/static/npm_dir/*" $(LNGS)
|
./manage.py makemessages --keep-pot --ignore "pretix/static/npm_dir/*" $(LNGS)
|
||||||
./manage.py makemessages --keep-pot -d djangojs --ignore "pretix/static/npm_dir/*" --ignore "pretix/helpers/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static.dist/*" --ignore "data/*" --ignore "pretix/static/rrule/*" --ignore "build/*" $(LNGS)
|
./manage.py makemessages --keep-pot -d djangojs --ignore "pretix/static/npm_dir/*" --ignore "pretix/helpers/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static.dist/*" --ignore "data/*" --ignore "pretix/static/rrule/*" --ignore "build/*" $(LNGS)
|
||||||
|
|
||||||
staticfiles: jsi18n
|
staticfiles: npminstall npmbuild jsi18n
|
||||||
./manage.py collectstatic --noinput
|
./manage.py collectstatic --noinput
|
||||||
|
|
||||||
compress: npminstall
|
compress:
|
||||||
./manage.py compress
|
./manage.py compress
|
||||||
|
|
||||||
jsi18n: localecompile
|
jsi18n: localecompile
|
||||||
@@ -25,8 +25,8 @@ coverage:
|
|||||||
coverage run -m py.test
|
coverage run -m py.test
|
||||||
|
|
||||||
npminstall:
|
npminstall:
|
||||||
# keep this in sync with pretix/_build.py!
|
npm ci
|
||||||
mkdir -p pretix/static.dist/node_prefix/
|
|
||||||
cp -r pretix/static/npm_dir/* pretix/static.dist/node_prefix/
|
npmbuild:
|
||||||
npm ci --prefix=pretix/static.dist/node_prefix
|
npm run build
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,4 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# 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/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2026.5.0.dev0"
|
__version__ = "2026.6.0.dev0"
|
||||||
|
|||||||
@@ -37,9 +37,11 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
|
# pretix needs to go before staticfiles
|
||||||
|
# so we can override the runserver command
|
||||||
'pretix.base',
|
'pretix.base',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
'pretix.control',
|
'pretix.control',
|
||||||
'pretix.presale',
|
'pretix.presale',
|
||||||
'pretix.multidomain',
|
'pretix.multidomain',
|
||||||
@@ -243,7 +245,6 @@ STORAGES = {
|
|||||||
|
|
||||||
COMPRESS_PRECOMPILERS = (
|
COMPRESS_PRECOMPILERS = (
|
||||||
('text/x-scss', 'django_libsass.SassCompiler'),
|
('text/x-scss', 'django_libsass.SassCompiler'),
|
||||||
('text/vue', 'pretix.helpers.compressor.VueCompiler'),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
COMPRESS_OFFLINE_CONTEXT = {
|
COMPRESS_OFFLINE_CONTEXT = {
|
||||||
|
|||||||
@@ -21,13 +21,13 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from setuptools.command.build import build
|
from setuptools.command.build import build
|
||||||
from setuptools.command.build_ext import build_ext
|
from setuptools.command.build_ext import build_ext
|
||||||
|
|
||||||
here = os.path.abspath(os.path.dirname(__file__))
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
project_root = os.path.abspath(os.path.join(here, '..', '..'))
|
||||||
npm_installed = False
|
npm_installed = False
|
||||||
|
|
||||||
|
|
||||||
@@ -35,14 +35,14 @@ def npm_install():
|
|||||||
global npm_installed
|
global npm_installed
|
||||||
|
|
||||||
if not npm_installed:
|
if not npm_installed:
|
||||||
# keep this in sync with Makefile!
|
subprocess.check_call('npm ci', shell=True, cwd=project_root)
|
||||||
node_prefix = os.path.join(here, 'static.dist', 'node_prefix')
|
|
||||||
os.makedirs(node_prefix, exist_ok=True)
|
|
||||||
shutil.copytree(os.path.join(here, 'static', 'npm_dir'), node_prefix, dirs_exist_ok=True)
|
|
||||||
subprocess.check_call('npm ci', shell=True, cwd=node_prefix)
|
|
||||||
npm_installed = True
|
npm_installed = True
|
||||||
|
|
||||||
|
|
||||||
|
def npm_build():
|
||||||
|
subprocess.check_call('npm run build', shell=True, cwd=project_root)
|
||||||
|
|
||||||
|
|
||||||
class CustomBuild(build):
|
class CustomBuild(build):
|
||||||
def run(self):
|
def run(self):
|
||||||
if "src" not in os.listdir(".") or "pretix" not in os.listdir("src"):
|
if "src" not in os.listdir(".") or "pretix" not in os.listdir("src"):
|
||||||
@@ -62,6 +62,7 @@ class CustomBuild(build):
|
|||||||
settings.COMPRESS_OFFLINE = True
|
settings.COMPRESS_OFFLINE = True
|
||||||
|
|
||||||
npm_install()
|
npm_install()
|
||||||
|
npm_build()
|
||||||
management.call_command('compilemessages', verbosity=1)
|
management.call_command('compilemessages', verbosity=1)
|
||||||
management.call_command('compilejsi18n', verbosity=1)
|
management.call_command('compilejsi18n', verbosity=1)
|
||||||
management.call_command('collectstatic', verbosity=1, interactive=False)
|
management.call_command('collectstatic', verbosity=1, interactive=False)
|
||||||
|
|||||||
@@ -47,3 +47,5 @@ HAS_MEMCACHED = False
|
|||||||
HAS_CELERY = False
|
HAS_CELERY = False
|
||||||
HAS_GEOIP = False
|
HAS_GEOIP = False
|
||||||
SENTRY_ENABLED = False
|
SENTRY_ENABLED = False
|
||||||
|
VITE_DEV_MODE = False
|
||||||
|
VITE_IGNORE = False
|
||||||
|
|||||||
@@ -133,37 +133,43 @@ class JobRunSerializer(serializers.Serializer):
|
|||||||
return not bool(self._errors)
|
return not bool(self._errors)
|
||||||
|
|
||||||
|
|
||||||
|
class ExportFormDataField(serializers.Field):
|
||||||
|
def get_attribute(self, instance):
|
||||||
|
return (instance.export_identifier, instance.export_form_data)
|
||||||
|
|
||||||
|
def to_representation(self, value):
|
||||||
|
export_identifier, export_form_data = value
|
||||||
|
exporter = self.context['exporters'].get(export_identifier)
|
||||||
|
if exporter:
|
||||||
|
return JobRunSerializer(exporter=exporter).to_representation(export_form_data)
|
||||||
|
else:
|
||||||
|
return export_form_data
|
||||||
|
|
||||||
|
def get_value(self, dictionary):
|
||||||
|
return dictionary
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
if "export_form_data" in data:
|
||||||
|
identifier = data.get('export_identifier', self.parent.instance.export_identifier if self.parent.instance else None)
|
||||||
|
exporter = self.context['exporters'].get(identifier)
|
||||||
|
if exporter:
|
||||||
|
return JobRunSerializer(exporter=exporter).to_internal_value(data["export_form_data"])
|
||||||
|
else:
|
||||||
|
return data['export_form_data']
|
||||||
|
|
||||||
|
|
||||||
class ScheduledExportSerializer(serializers.ModelSerializer):
|
class ScheduledExportSerializer(serializers.ModelSerializer):
|
||||||
schedule_next_run = serializers.DateTimeField(read_only=True)
|
schedule_next_run = serializers.DateTimeField(read_only=True)
|
||||||
export_identifier = serializers.ChoiceField(choices=[])
|
export_identifier = serializers.ChoiceField(choices=[])
|
||||||
locale = serializers.ChoiceField(choices=settings.LANGUAGES, default='en')
|
locale = serializers.ChoiceField(choices=settings.LANGUAGES, default='en')
|
||||||
owner = serializers.SlugRelatedField(slug_field='email', read_only=True)
|
owner = serializers.SlugRelatedField(slug_field='email', read_only=True)
|
||||||
error_counter = serializers.IntegerField(read_only=True)
|
error_counter = serializers.IntegerField(read_only=True)
|
||||||
|
export_form_data = ExportFormDataField()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields['export_identifier'].choices = [(e, e) for e in self.context['exporters']]
|
self.fields['export_identifier'].choices = [(e, e) for e in self.context['exporters']]
|
||||||
|
|
||||||
def validate(self, attrs):
|
|
||||||
if attrs.get("export_form_data"):
|
|
||||||
identifier = attrs.get('export_identifier', self.instance.export_identifier if self.instance else None)
|
|
||||||
exporter = self.context['exporters'].get(identifier)
|
|
||||||
if exporter:
|
|
||||||
try:
|
|
||||||
attrs["export_form_data"] = JobRunSerializer(exporter=exporter).to_internal_value(attrs["export_form_data"])
|
|
||||||
except ValidationError as e:
|
|
||||||
raise ValidationError({"export_form_data": e.detail})
|
|
||||||
else:
|
|
||||||
raise ValidationError({"export_identifier": ["Unknown exporter."]})
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def to_representation(self, instance):
|
|
||||||
repr = super().to_representation(instance)
|
|
||||||
exporter = self.context['exporters'].get(instance.export_identifier)
|
|
||||||
if exporter:
|
|
||||||
repr["export_form_data"] = JobRunSerializer(exporter=exporter).to_representation(repr["export_form_data"])
|
|
||||||
return repr
|
|
||||||
|
|
||||||
def validate_mail_additional_recipients(self, value):
|
def validate_mail_additional_recipients(self, value):
|
||||||
d = value.replace(' ', '')
|
d = value.replace(' ', '')
|
||||||
if len(d.split(',')) > 25:
|
if len(d.split(',')) > 25:
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ class PrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
|||||||
return value
|
return value
|
||||||
return super().to_representation(value)
|
return super().to_representation(value)
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
value = super().to_internal_value(data)
|
||||||
|
if value is not None:
|
||||||
|
return value.pk
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class FormFieldWrapperField(serializers.Field):
|
class FormFieldWrapperField(serializers.Field):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -66,13 +66,14 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
expand_nested = self.context['request'].query_params.getlist('expand')
|
||||||
|
|
||||||
if 'linked_giftcard' in self.context['request'].query_params.getlist('expand'):
|
if 'linked_giftcard' in expand_nested:
|
||||||
if not self.context["can_read_giftcards"]:
|
if not self.context["can_read_giftcards"]:
|
||||||
raise PermissionDenied("No permission to access gift card details.")
|
raise PermissionDenied("No permission to access gift card details.")
|
||||||
|
|
||||||
self.fields['linked_giftcard'] = NestedGiftCardSerializer(read_only=True, context=self.context)
|
self.fields['linked_giftcard'] = NestedGiftCardSerializer(read_only=True, context=self.context)
|
||||||
if 'linked_giftcard.owner_ticket' in self.context['request'].query_params.getlist('expand'):
|
if 'linked_giftcard.owner_ticket' in expand_nested:
|
||||||
self.fields['linked_giftcard'].fields['owner_ticket'] = NestedOrderPositionSerializer(read_only=True, context=self.context)
|
self.fields['linked_giftcard'].fields['owner_ticket'] = NestedOrderPositionSerializer(read_only=True, context=self.context)
|
||||||
else:
|
else:
|
||||||
self.fields['linked_giftcard'] = serializers.PrimaryKeyRelatedField(
|
self.fields['linked_giftcard'] = serializers.PrimaryKeyRelatedField(
|
||||||
@@ -81,17 +82,27 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
queryset=self.context['organizer'].issued_gift_cards.all()
|
queryset=self.context['organizer'].issued_gift_cards.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'linked_orderposition' in self.context['request'].query_params.getlist('expand'):
|
# keep linked_orderposition (singular) for backwards compatibility, will be overwritten in self.validate
|
||||||
# Permission Check performed in to_representation
|
self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField(
|
||||||
self.fields['linked_orderposition'] = NestedOrderPositionSerializer(read_only=True)
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']),
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'linked_orderposition' in expand_nested or 'linked_orderpositions' in expand_nested:
|
||||||
|
self.fields['linked_orderpositions'] = NestedOrderPositionSerializer(
|
||||||
|
many=True,
|
||||||
|
read_only=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField(
|
self.fields['linked_orderpositions'] = serializers.PrimaryKeyRelatedField(
|
||||||
|
many=True,
|
||||||
required=False,
|
required=False,
|
||||||
allow_null=True,
|
allow_null=True,
|
||||||
queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']),
|
queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']),
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'customer' in self.context['request'].query_params.getlist('expand'):
|
if 'customer' in expand_nested:
|
||||||
if not self.context["can_read_customers"]:
|
if not self.context["can_read_customers"]:
|
||||||
raise PermissionDenied("No permission to access customer details.")
|
raise PermissionDenied("No permission to access customer details.")
|
||||||
|
|
||||||
@@ -106,6 +117,21 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
data = super().validate(data)
|
data = super().validate(data)
|
||||||
|
if 'linked_orderposition' in data:
|
||||||
|
linked_orderposition = data['linked_orderposition']
|
||||||
|
# backwards-compatibility
|
||||||
|
if 'linked_orderpositions' in data:
|
||||||
|
raise ValidationError({
|
||||||
|
'linked_orderposition': 'You cannot use linked_orderposition and linked_orderpositions at the same time.'
|
||||||
|
})
|
||||||
|
if self.instance and self.instance.linked_orderpositions.count() > 1:
|
||||||
|
raise ValidationError({
|
||||||
|
'linked_orderposition': 'There are more than one linked_orderposition. You need to use linked_orderpositions.'
|
||||||
|
})
|
||||||
|
|
||||||
|
data['linked_orderpositions'] = [linked_orderposition] if linked_orderposition else []
|
||||||
|
del data['linked_orderposition']
|
||||||
|
|
||||||
if 'type' in data and 'identifier' in data:
|
if 'type' in data and 'identifier' in data:
|
||||||
qs = self.context['organizer'].reusable_media.filter(
|
qs = self.context['organizer'].reusable_media.filter(
|
||||||
identifier=data['identifier'], type=data['type']
|
identifier=data['identifier'], type=data['type']
|
||||||
@@ -121,14 +147,28 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
def to_representation(self, instance):
|
def to_representation(self, instance):
|
||||||
r = super().to_representation(instance)
|
r = super().to_representation(instance)
|
||||||
request = self.context.get('request')
|
request = self.context.get('request')
|
||||||
|
|
||||||
|
ops = r.get('linked_orderpositions', [])
|
||||||
# late permission evaluations for checks that depend on the actual linked events
|
# late permission evaluations for checks that depend on the actual linked events
|
||||||
expand_nested = self.context['request'].query_params.getlist('expand')
|
expand_nested = self.context['request'].query_params.getlist('expand')
|
||||||
perm_holder = request.auth if isinstance(request.auth, (Device, TeamAPIToken)) else request.user
|
perm_holder = request.auth if isinstance(request.auth, (Device, TeamAPIToken)) else request.user
|
||||||
if 'linked_orderposition' in expand_nested:
|
if ops and 'linked_orderposition' in expand_nested or 'linked_orderpositions' in expand_nested:
|
||||||
if instance.linked_orderposition is not None:
|
ops_noperm = []
|
||||||
event = instance.linked_orderposition.order.event
|
for lop in instance.linked_orderpositions.all():
|
||||||
|
event = lop.order.event
|
||||||
if not perm_holder.has_event_permission(event.organizer, event, 'event.orders:read', request):
|
if not perm_holder.has_event_permission(event.organizer, event, 'event.orders:read', request):
|
||||||
r['linked_orderposition'] = {'id': instance.linked_orderposition.id}
|
ops_noperm.append(lop.id)
|
||||||
|
if ops_noperm:
|
||||||
|
ops = [
|
||||||
|
{'id': op['id']} if op['id'] in ops_noperm
|
||||||
|
else op
|
||||||
|
for op in ops
|
||||||
|
]
|
||||||
|
r['linked_orderpositions'] = ops
|
||||||
|
|
||||||
|
# add linked_orderposition (singular) for backwards compatibility
|
||||||
|
if len(ops) < 2:
|
||||||
|
r['linked_orderposition'] = ops[0] if ops else None
|
||||||
|
|
||||||
if 'linked_giftcard.owner_ticket' in expand_nested:
|
if 'linked_giftcard.owner_ticket' in expand_nested:
|
||||||
gc = instance.linked_giftcard
|
gc = instance.linked_giftcard
|
||||||
@@ -148,10 +188,12 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
'updated',
|
'updated',
|
||||||
'type',
|
'type',
|
||||||
'identifier',
|
'identifier',
|
||||||
|
'claim_token',
|
||||||
|
'label',
|
||||||
'active',
|
'active',
|
||||||
'expires',
|
'expires',
|
||||||
'customer',
|
'customer',
|
||||||
'linked_orderposition',
|
'linked_orderpositions',
|
||||||
'linked_giftcard',
|
'linked_giftcard',
|
||||||
'info',
|
'info',
|
||||||
'notes',
|
'notes',
|
||||||
|
|||||||
@@ -1043,13 +1043,15 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
requested_valid_from = serializers.DateTimeField(required=False, allow_null=True)
|
requested_valid_from = serializers.DateTimeField(required=False, allow_null=True)
|
||||||
use_reusable_medium = serializers.PrimaryKeyRelatedField(queryset=ReusableMedium.objects.none(),
|
use_reusable_medium = serializers.PrimaryKeyRelatedField(queryset=ReusableMedium.objects.none(),
|
||||||
required=False, allow_null=True)
|
required=False, allow_null=True)
|
||||||
|
add_to_reusable_medium = serializers.PrimaryKeyRelatedField(queryset=ReusableMedium.objects.none(),
|
||||||
|
required=False, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OrderPosition
|
model = OrderPosition
|
||||||
fields = ('positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
|
fields = ('positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
|
||||||
'company', 'street', 'zipcode', 'city', 'country', 'state', 'is_bundled',
|
'company', 'street', 'zipcode', 'city', 'country', 'state', 'is_bundled',
|
||||||
'secret', 'addon_to', 'subevent', 'answers', 'seat', 'voucher', 'valid_from', 'valid_until',
|
'secret', 'addon_to', 'subevent', 'answers', 'seat', 'voucher', 'valid_from', 'valid_until',
|
||||||
'requested_valid_from', 'use_reusable_medium', 'discount')
|
'requested_valid_from', 'use_reusable_medium', 'add_to_reusable_medium', 'discount')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -1061,6 +1063,8 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
if 'use_reusable_medium' in self.fields:
|
if 'use_reusable_medium' in self.fields:
|
||||||
self.fields['use_reusable_medium'].queryset = ReusableMedium.objects.all()
|
self.fields['use_reusable_medium'].queryset = ReusableMedium.objects.all()
|
||||||
|
if 'add_to_reusable_medium' in self.fields:
|
||||||
|
self.fields['add_to_reusable_medium'].queryset = ReusableMedium.objects.all()
|
||||||
|
|
||||||
def validate_secret(self, secret):
|
def validate_secret(self, secret):
|
||||||
if secret and OrderPosition.all.filter(order__event=self.context['event'], secret=secret).exists():
|
if secret and OrderPosition.all.filter(order__event=self.context['event'], secret=secret).exists():
|
||||||
@@ -1076,6 +1080,9 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
)
|
)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
def validate_add_to_reusable_medium(self, m):
|
||||||
|
return self.validate_use_reusable_medium(m)
|
||||||
|
|
||||||
def validate_item(self, item):
|
def validate_item(self, item):
|
||||||
if item.event != self.context['event']:
|
if item.event != self.context['event']:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
@@ -1149,6 +1156,13 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{'discount': ['You can only specify a discount if you do the price computation, but price is not set.']}
|
{'discount': ['You can only specify a discount if you do the price computation, but price is not set.']}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if 'use_reusable_medium' in data and 'add_to_reusable_medium' in data:
|
||||||
|
raise ValidationError({
|
||||||
|
'use_reusable_medium': ['You can only specify either use_reusable_medium or add_to_reusable_medium.'],
|
||||||
|
'add_to_reusable_medium': ['You can only specify either use_reusable_medium or add_to_reusable_medium.'],
|
||||||
|
})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@@ -1588,7 +1602,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
pos_data['attendee_name_parts'] = {
|
pos_data['attendee_name_parts'] = {
|
||||||
'_legacy': attendee_name
|
'_legacy': attendee_name
|
||||||
}
|
}
|
||||||
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k != 'answers' and k != '_quotas' and k != 'use_reusable_medium'})
|
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k not in ('answers', '_quotas', 'use_reusable_medium', 'add_to_reusable_medium')})
|
||||||
if simulate:
|
if simulate:
|
||||||
pos.order = order._wrapped
|
pos.order = order._wrapped
|
||||||
else:
|
else:
|
||||||
@@ -1662,6 +1676,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
for pos_data in positions_data:
|
for pos_data in positions_data:
|
||||||
answers_data = pos_data.pop('answers', [])
|
answers_data = pos_data.pop('answers', [])
|
||||||
use_reusable_medium = pos_data.pop('use_reusable_medium', None)
|
use_reusable_medium = pos_data.pop('use_reusable_medium', None)
|
||||||
|
add_to_reusable_medium = pos_data.pop('add_to_reusable_medium', None)
|
||||||
pos = pos_data['__instance']
|
pos = pos_data['__instance']
|
||||||
pos._calculate_tax(invoice_address=ia)
|
pos._calculate_tax(invoice_address=ia)
|
||||||
|
|
||||||
@@ -1703,10 +1718,25 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
answ.options.add(*options)
|
answ.options.add(*options)
|
||||||
|
|
||||||
if use_reusable_medium:
|
if use_reusable_medium:
|
||||||
use_reusable_medium.linked_orderposition = pos
|
for op_pk in use_reusable_medium.linked_orderpositions.values_list('pk', flat=True):
|
||||||
use_reusable_medium.save(update_fields=['linked_orderposition'])
|
use_reusable_medium.log_action(
|
||||||
|
'pretix.reusable_medium.linked_orderposition.removed',
|
||||||
|
data={
|
||||||
|
'linked_orderposition': op_pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
use_reusable_medium.linked_orderpositions.set([pos])
|
||||||
use_reusable_medium.log_action(
|
use_reusable_medium.log_action(
|
||||||
'pretix.reusable_medium.linked_orderposition.changed',
|
'pretix.reusable_medium.linked_orderposition.added',
|
||||||
|
data={
|
||||||
|
'by_order': order.code,
|
||||||
|
'linked_orderposition': pos.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elif add_to_reusable_medium:
|
||||||
|
add_to_reusable_medium.linked_orderpositions.add(pos)
|
||||||
|
add_to_reusable_medium.log_action(
|
||||||
|
'pretix.reusable_medium.linked_orderposition.added',
|
||||||
data={
|
data={
|
||||||
'by_order': order.code,
|
'by_order': order.code,
|
||||||
'linked_orderposition': pos.pk,
|
'linked_orderposition': pos.pk,
|
||||||
|
|||||||
@@ -491,6 +491,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
)
|
)
|
||||||
raw_barcode_for_checkin = None
|
raw_barcode_for_checkin = None
|
||||||
from_revoked_secret = False
|
from_revoked_secret = False
|
||||||
|
reusable_medium_used = None
|
||||||
if simulate:
|
if simulate:
|
||||||
common_checkin_args['__fake_arg_to_prevent_this_from_being_saved'] = True
|
common_checkin_args['__fake_arg_to_prevent_this_from_being_saved'] = True
|
||||||
|
|
||||||
@@ -521,11 +522,12 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
# with respecting the force option), or it's a reusable medium (-> proceed with that)
|
# with respecting the force option), or it's a reusable medium (-> proceed with that)
|
||||||
if not op_candidates:
|
if not op_candidates:
|
||||||
try:
|
try:
|
||||||
media = ReusableMedium.objects.select_related('linked_orderposition').active().get(
|
media = ReusableMedium.objects.active().filter(
|
||||||
|
Exists(ReusableMedium.linked_orderpositions.through.objects.filter(reusablemedium_id=OuterRef('pk')))
|
||||||
|
).get(
|
||||||
organizer_id=checkinlists[0].event.organizer_id,
|
organizer_id=checkinlists[0].event.organizer_id,
|
||||||
type=source_type,
|
type=source_type,
|
||||||
identifier=raw_barcode,
|
identifier=raw_barcode,
|
||||||
linked_orderposition__isnull=False,
|
|
||||||
)
|
)
|
||||||
raw_barcode_for_checkin = raw_barcode
|
raw_barcode_for_checkin = raw_barcode
|
||||||
except ReusableMedium.DoesNotExist:
|
except ReusableMedium.DoesNotExist:
|
||||||
@@ -628,7 +630,9 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
'list': MiniCheckinListSerializer(list_by_event[revoked_matches[0].event_id]).data,
|
'list': MiniCheckinListSerializer(list_by_event[revoked_matches[0].event_id]).data,
|
||||||
}, status=400)
|
}, status=400)
|
||||||
else:
|
else:
|
||||||
if media.linked_orderposition.order.event_id not in list_by_event:
|
linked_ops = media.linked_orderpositions.all().select_related("order").prefetch_related("addons")
|
||||||
|
linked_event_ids = {op.order.event_id for op in linked_ops}
|
||||||
|
if not any(event_id in list_by_event for event_id in linked_event_ids):
|
||||||
# Medium exists but connected ticket is for the wrong event
|
# Medium exists but connected ticket is for the wrong event
|
||||||
if not simulate:
|
if not simulate:
|
||||||
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
||||||
@@ -654,28 +658,91 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
'checkin_texts': [],
|
'checkin_texts': [],
|
||||||
'list': MiniCheckinListSerializer(checkinlists[0]).data,
|
'list': MiniCheckinListSerializer(checkinlists[0]).data,
|
||||||
}, status=404)
|
}, status=404)
|
||||||
op_candidates = [media.linked_orderposition]
|
op_candidates = []
|
||||||
if list_by_event[media.linked_orderposition.order.event_id].addon_match:
|
for op in linked_ops:
|
||||||
op_candidates += list(media.linked_orderposition.addons.all())
|
if op.order.event_id in list_by_event:
|
||||||
|
reusable_medium_used = media
|
||||||
|
op_candidates.append(op)
|
||||||
|
if list_by_event[op.order.event_id].addon_match:
|
||||||
|
op_candidates += list(op.addons.all())
|
||||||
|
|
||||||
# 3. Handle the "multiple options found" case: Except for the unlikely case of a secret being also a valid primary
|
# 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
|
# key on the same list, we're probably dealing with multiple linked_orderpositions or the ``addon_match`` case
|
||||||
# which add-on has the right product.
|
# here and need to figure out which op has the right product. This basically is a valid-for-checkin-test on every op.
|
||||||
if len(op_candidates) > 1:
|
if len(op_candidates) > 1:
|
||||||
op_candidates_matching_product = [
|
|
||||||
op for op in op_candidates
|
|
||||||
if (
|
|
||||||
(list_by_event[op.order.event_id].addon_match or op.secret == raw_barcode or legacy_url_support) and
|
|
||||||
(list_by_event[op.order.event_id].all_products or op.item_id in {i.pk for i in list_by_event[op.order.event_id].limit_products.all()})
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
if len(op_candidates_matching_product) == 0:
|
if not reusable_medium_used:
|
||||||
# None of the found add-ons has the correct product, too bad! We could just error out here, but
|
# 3a. First, we clean up that we made an imprecise query above. If a scan is made for multiple check-in lists,
|
||||||
|
# we have queried ``addon_to__secret=raw_barcode``, even if some of the lists in question do not allow addon
|
||||||
|
# matching. So we accept all candidates that match one of these cases:
|
||||||
|
# - Exactly the ticket secret we scanned (because that's always a possible result)
|
||||||
|
# - Exactly the ticket pk we scanned (on legacy endpoints)
|
||||||
|
# - An add-on on a list that allows add-on matching
|
||||||
|
# This is not necessary when a reusable media was used, since in that case we already obeyed list.addon_match
|
||||||
|
# correctly above.
|
||||||
|
op_candidates_filtered = [
|
||||||
|
op for op in op_candidates
|
||||||
|
if (
|
||||||
|
op.secret == raw_barcode or
|
||||||
|
list_by_event[op.order.event_id].addon_match or
|
||||||
|
(str(op.pk) == raw_barcode and legacy_url_support and not untrusted_input)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
op_candidates_filtered = op_candidates
|
||||||
|
|
||||||
|
if len(op_candidates_filtered) > 1:
|
||||||
|
# 3b. If we still have multiple candidates, we filter by product based on the check-in list configuration.
|
||||||
|
# This is relevant for the addon_match scenario where the scanned ticket has multiple add-ons, but only
|
||||||
|
# one is contained in the check-in list used to scan. It makes sense to filter this first, since it is a
|
||||||
|
# "static" check, i.e. scanning the same QR code on the same check-in list will always do the same, no matter
|
||||||
|
# when I scan it, and it is "intentional" filtering in the sense that the admin configured this behaviour
|
||||||
|
# into the check-in list.
|
||||||
|
op_candidates_filtered = [
|
||||||
|
op for op in op_candidates_filtered
|
||||||
|
if list_by_event[op.order.event_id].all_products or op.item_id in {i.pk for i in list_by_event[op.order.event_id].limit_products.all()}
|
||||||
|
]
|
||||||
|
|
||||||
|
if len(op_candidates_filtered) > 1:
|
||||||
|
# 3c. If we still have multiple candidates, we filter by validity date. This was introduced for the case where
|
||||||
|
# a reusable media refers to two tickets, one currently valid and one expired or in the future. Howeer,
|
||||||
|
# it could in theory also happen with two add-ons being on the same check-in list but without overlapping
|
||||||
|
# validity. It makes sense to filter this "after" the previous checks since it is not "intentional" filtering
|
||||||
|
# configured by the admin but "accidental" filtering that depends on the time of execution.
|
||||||
|
op_candidates_filtered = [
|
||||||
|
op for op in op_candidates_filtered
|
||||||
|
if (
|
||||||
|
(not op.valid_from or op.valid_from <= datetime) and
|
||||||
|
(not op.valid_until or op.valid_until > datetime)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
if len(op_candidates_filtered) == 0:
|
||||||
|
# None of the ops is valid today or 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.
|
# 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.
|
# To improve the error message, we select the op that will "work next" or - if none matches - "worked last".
|
||||||
op_candidates = [op_candidates[0]]
|
op_candidate = None
|
||||||
elif len(op_candidates_matching_product) > 1:
|
for op in op_candidates:
|
||||||
|
if (
|
||||||
|
op.valid_from and op.valid_from > datetime and
|
||||||
|
(not op_candidate or op.valid_from < op_candidate.valid_from)
|
||||||
|
):
|
||||||
|
op_candidate = op
|
||||||
|
|
||||||
|
if not op_candidate:
|
||||||
|
# no candidate in the future, get closest in the past
|
||||||
|
for op in op_candidates:
|
||||||
|
if (
|
||||||
|
op.valid_until and op.valid_until < datetime and
|
||||||
|
(not op_candidate or op.valid_until > op_candidate.valid_until)
|
||||||
|
):
|
||||||
|
op_candidate = op
|
||||||
|
|
||||||
|
if not op_candidate:
|
||||||
|
op_candidate = op_candidates[0]
|
||||||
|
|
||||||
|
op_candidates = [op_candidate]
|
||||||
|
elif len(op_candidates_filtered) > 1:
|
||||||
# It's still ambiguous, we'll error out.
|
# 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
|
# 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.
|
# base product according to our order_by above.
|
||||||
@@ -709,7 +776,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||||
}, status=400)
|
}, status=400)
|
||||||
else:
|
else:
|
||||||
op_candidates = op_candidates_matching_product
|
op_candidates = op_candidates_filtered
|
||||||
|
|
||||||
op = op_candidates[0]
|
op = op_candidates[0]
|
||||||
common_checkin_args['list'] = list_by_event[op.order.event_id]
|
common_checkin_args['list'] = list_by_event[op.order.event_id]
|
||||||
@@ -721,7 +788,10 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
|||||||
if str(q.pk) in answers_data:
|
if str(q.pk) in answers_data:
|
||||||
try:
|
try:
|
||||||
if q.type == Question.TYPE_FILE:
|
if q.type == Question.TYPE_FILE:
|
||||||
given_answers[q] = _handle_file_upload(answers_data[str(q.pk)], user, auth)
|
if answers_data[str(q.pk)]:
|
||||||
|
given_answers[q] = _handle_file_upload(answers_data[str(q.pk)], user, auth)
|
||||||
|
else:
|
||||||
|
given_answers[q] = None
|
||||||
else:
|
else:
|
||||||
given_answers[q] = q.clean_answer(answers_data[str(q.pk)])
|
given_answers[q] = q.clean_answer(answers_data[str(q.pk)])
|
||||||
except (ValidationError, BaseValidationError):
|
except (ValidationError, BaseValidationError):
|
||||||
|
|||||||
@@ -53,10 +53,12 @@ with scopes_disabled():
|
|||||||
customer = django_filters.CharFilter(field_name='customer__identifier')
|
customer = django_filters.CharFilter(field_name='customer__identifier')
|
||||||
updated_since = django_filters.IsoDateTimeFilter(field_name='updated', lookup_expr='gte')
|
updated_since = django_filters.IsoDateTimeFilter(field_name='updated', lookup_expr='gte')
|
||||||
created_since = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='gte')
|
created_since = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='gte')
|
||||||
|
# backwards-compatible
|
||||||
|
linked_orderposition = django_filters.NumberFilter(field_name='linked_orderpositions__id')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReusableMedium
|
model = ReusableMedium
|
||||||
fields = ['identifier', 'type', 'active', 'customer', 'linked_orderposition', 'linked_giftcard']
|
fields = ['identifier', 'type', 'active', 'customer', 'linked_orderpositions', 'linked_giftcard']
|
||||||
|
|
||||||
|
|
||||||
class ReusableMediaViewSet(viewsets.ModelViewSet):
|
class ReusableMediaViewSet(viewsets.ModelViewSet):
|
||||||
@@ -75,7 +77,7 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
|||||||
).order_by().values('card').annotate(s=Sum('value')).values('s')
|
).order_by().values('card').annotate(s=Sum('value')).values('s')
|
||||||
return self.request.organizer.reusable_media.prefetch_related(
|
return self.request.organizer.reusable_media.prefetch_related(
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'linked_orderposition',
|
'linked_orderpositions',
|
||||||
queryset=OrderPosition.objects.select_related(
|
queryset=OrderPosition.objects.select_related(
|
||||||
'order', 'order__event', 'order__event__organizer', 'seat',
|
'order', 'order__event', 'order__event__organizer', 'seat',
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
@@ -117,14 +119,38 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
@transaction.atomic()
|
@transaction.atomic()
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
ReusableMedium.objects.select_for_update(of=OF_SELF).get(pk=self.get_object().pk)
|
rm = ReusableMedium.objects.select_for_update(of=OF_SELF).get(pk=self.get_object().pk)
|
||||||
|
prev_linked_ops_pks = list(rm.linked_orderpositions.values_list("pk", flat=True))
|
||||||
inst = serializer.save(identifier=serializer.instance.identifier, type=serializer.instance.type)
|
inst = serializer.save(identifier=serializer.instance.identifier, type=serializer.instance.type)
|
||||||
inst.log_action(
|
linked_ops_pks = inst.linked_orderpositions.values_list("pk", flat=True)
|
||||||
'pretix.reusable_medium.changed',
|
for op_pk in prev_linked_ops_pks:
|
||||||
user=self.request.user,
|
if op_pk not in linked_ops_pks:
|
||||||
auth=self.request.auth,
|
inst.log_action(
|
||||||
data=self.request.data,
|
'pretix.reusable_medium.linked_orderposition.removed',
|
||||||
)
|
user=self.request.user,
|
||||||
|
auth=self.request.auth,
|
||||||
|
data={
|
||||||
|
'linked_orderposition': op_pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
for op_pk in linked_ops_pks:
|
||||||
|
if op_pk not in prev_linked_ops_pks:
|
||||||
|
inst.log_action(
|
||||||
|
'pretix.reusable_medium.linked_orderposition.added',
|
||||||
|
user=self.request.user,
|
||||||
|
auth=self.request.auth,
|
||||||
|
data={
|
||||||
|
'linked_orderposition': op_pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
data = {k: v for k, v in self.request.data.items() if k not in ('linked_orderposition', 'linked_orderpositions')}
|
||||||
|
if data:
|
||||||
|
inst.log_action(
|
||||||
|
'pretix.reusable_medium.changed',
|
||||||
|
user=self.request.user,
|
||||||
|
auth=self.request.auth,
|
||||||
|
data=data,
|
||||||
|
)
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
def perform_destroy(self, instance):
|
def perform_destroy(self, instance):
|
||||||
@@ -157,7 +183,6 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
|||||||
type=s.validated_data["type"],
|
type=s.validated_data["type"],
|
||||||
identifier=s.validated_data["identifier"],
|
identifier=s.validated_data["identifier"],
|
||||||
)
|
)
|
||||||
m.linked_orderposition = None # not relevant for cross-organizer
|
|
||||||
m.customer = None # not relevant for cross-organizer
|
m.customer = None # not relevant for cross-organizer
|
||||||
s = self.get_serializer(m)
|
s = self.get_serializer(m)
|
||||||
return Response({"result": s.data})
|
return Response({"result": s.data})
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ with scopes_disabled():
|
|||||||
)
|
)
|
||||||
).values('id')
|
).values('id')
|
||||||
|
|
||||||
matching_media = ReusableMedium.objects.filter(identifier=u).values_list('linked_orderposition__order_id', flat=True)
|
matching_media = ReusableMedium.objects.filter(identifier=u).values_list('linked_orderpositions__order_id', flat=True)
|
||||||
|
|
||||||
mainq = (
|
mainq = (
|
||||||
code
|
code
|
||||||
@@ -1034,7 +1034,7 @@ with scopes_disabled():
|
|||||||
search = django_filters.CharFilter(method='search_qs')
|
search = django_filters.CharFilter(method='search_qs')
|
||||||
|
|
||||||
def search_qs(self, queryset, name, value):
|
def search_qs(self, queryset, name, value):
|
||||||
matching_media = ReusableMedium.objects.filter(identifier=value).values_list('linked_orderposition', flat=True)
|
matching_media = ReusableMedium.objects.filter(identifier=value).values_list('linked_orderpositions', flat=True)
|
||||||
return queryset.filter(
|
return queryset.filter(
|
||||||
Q(secret__istartswith=value)
|
Q(secret__istartswith=value)
|
||||||
| Q(attendee_name_cached__icontains=value)
|
| Q(attendee_name_cached__icontains=value)
|
||||||
|
|||||||
@@ -408,6 +408,12 @@ def register_default_webhook_events(sender, **kwargs):
|
|||||||
_('This includes product added or deleted and changes to nested objects like '
|
_('This includes product added or deleted and changes to nested objects like '
|
||||||
'variations or bundles.'),
|
'variations or bundles.'),
|
||||||
),
|
),
|
||||||
|
ParametrizedItemWebhookEvent(
|
||||||
|
'pretix.event.quota.*',
|
||||||
|
_('Quota changed'),
|
||||||
|
_('This includes related events like creation, deletion, opening or closing of quotas. '
|
||||||
|
'No webhook is sent for changes to the resulting availability.'),
|
||||||
|
),
|
||||||
ParametrizedEventWebhookEvent(
|
ParametrizedEventWebhookEvent(
|
||||||
'pretix.event.live.activated',
|
'pretix.event.live.activated',
|
||||||
_('Shop taken live'),
|
_('Shop taken live'),
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ class OrderListExporter(MultiSheetListExporter):
|
|||||||
|
|
||||||
def _get_all_payment_methods(self, qs):
|
def _get_all_payment_methods(self, qs):
|
||||||
pps = dict(get_all_payment_providers())
|
pps = dict(get_all_payment_providers())
|
||||||
return sorted([(pp, pps[pp]) for pp in set(
|
return sorted([(pp, pps.get(pp, pp)) for pp in set(
|
||||||
OrderPayment.objects.exclude(provider='free').filter(order__event__in=self.events).values_list(
|
OrderPayment.objects.exclude(provider='free').filter(order__event__in=self.events).values_list(
|
||||||
'provider', flat=True
|
'provider', flat=True
|
||||||
).distinct()
|
).distinct()
|
||||||
@@ -330,6 +330,7 @@ class OrderListExporter(MultiSheetListExporter):
|
|||||||
taxsum=Sum('tax_value'), grosssum=Sum('value')
|
taxsum=Sum('tax_value'), grosssum=Sum('value')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
payment_methods = None
|
||||||
if form_data.get('include_payment_amounts'):
|
if form_data.get('include_payment_amounts'):
|
||||||
payment_sum_cache = {
|
payment_sum_cache = {
|
||||||
(o['order__id'], o['provider']): o['grosssum'] for o in
|
(o['order__id'], o['provider']): o['grosssum'] for o in
|
||||||
@@ -347,6 +348,7 @@ class OrderListExporter(MultiSheetListExporter):
|
|||||||
grosssum=Sum('amount')
|
grosssum=Sum('amount')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
payment_methods = self._get_all_payment_methods(qs)
|
||||||
sum_cache = {
|
sum_cache = {
|
||||||
(o['order__id'], o['tax_rate']): o for o in
|
(o['order__id'], o['tax_rate']): o for o in
|
||||||
OrderPosition.objects.values('tax_rate', 'order__id').order_by().annotate(
|
OrderPosition.objects.values('tax_rate', 'order__id').order_by().annotate(
|
||||||
@@ -434,7 +436,6 @@ class OrderListExporter(MultiSheetListExporter):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if form_data.get('include_payment_amounts'):
|
if form_data.get('include_payment_amounts'):
|
||||||
payment_methods = self._get_all_payment_methods(qs)
|
|
||||||
for id, vn in payment_methods:
|
for id, vn in payment_methods:
|
||||||
row.append(
|
row.append(
|
||||||
payment_sum_cache.get((order.id, id), Decimal('0.00')) -
|
payment_sum_cache.get((order.id, id), Decimal('0.00')) -
|
||||||
|
|||||||
@@ -20,12 +20,13 @@
|
|||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from django.db.models import Prefetch
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.formats import date_format
|
from django.utils.formats import date_format
|
||||||
from django.utils.translation import gettext_lazy as _, pgettext, pgettext_lazy
|
from django.utils.translation import gettext_lazy as _, pgettext, pgettext_lazy
|
||||||
|
|
||||||
from ..exporter import ListExporter, OrganizerLevelExportMixin
|
from ..exporter import ListExporter, OrganizerLevelExportMixin
|
||||||
from ..models import ReusableMedium
|
from ..models import OrderPosition, ReusableMedium
|
||||||
from ..signals import register_multievent_data_exporters
|
from ..signals import register_multievent_data_exporters
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +45,9 @@ class ReusableMediaExporter(OrganizerLevelExportMixin, ListExporter):
|
|||||||
media = ReusableMedium.objects.filter(
|
media = ReusableMedium.objects.filter(
|
||||||
organizer=self.organizer,
|
organizer=self.organizer,
|
||||||
).select_related(
|
).select_related(
|
||||||
'customer', 'linked_orderposition', 'linked_giftcard',
|
'customer', 'linked_giftcard',
|
||||||
|
).prefetch_related(
|
||||||
|
Prefetch('linked_orderpositions', queryset=OrderPosition.objects.select_related("order"))
|
||||||
).order_by('created')
|
).order_by('created')
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
@@ -61,18 +64,23 @@ class ReusableMediaExporter(OrganizerLevelExportMixin, ListExporter):
|
|||||||
yield headers
|
yield headers
|
||||||
yield self.ProgressSetTotal(total=media.count())
|
yield self.ProgressSetTotal(total=media.count())
|
||||||
|
|
||||||
|
can_read_giftcards = self.permission_holder.has_organizer_permission(self.organizer, 'organizer.giftcards:read')
|
||||||
|
|
||||||
for medium in media.iterator(chunk_size=1000):
|
for medium in media.iterator(chunk_size=1000):
|
||||||
row = [
|
giftcard_secret = medium.linked_giftcard.secret if medium.linked_giftcard_id else ''
|
||||||
|
if giftcard_secret and not can_read_giftcards:
|
||||||
|
giftcard_secret = giftcard_secret[:3] + "…"
|
||||||
|
|
||||||
|
yield [
|
||||||
medium.type,
|
medium.type,
|
||||||
medium.identifier,
|
medium.identifier,
|
||||||
_('Yes') if medium.active else _('No'),
|
_('Yes') if medium.active else _('No'),
|
||||||
date_format(medium.expires, 'SHORT_DATETIME_FORMAT') if medium.expires else '',
|
date_format(medium.expires, 'SHORT_DATETIME_FORMAT') if medium.expires else '',
|
||||||
medium.customer.identifier if medium.customer_id else '',
|
medium.customer.identifier if medium.customer_id else '',
|
||||||
f"{medium.linked_orderposition.order.code}-{medium.linked_orderposition.positionid}" if medium.linked_orderposition_id else '',
|
', '.join([f"{op.order.code}-{op.positionid}" for op in medium.linked_orderpositions.all()]),
|
||||||
medium.linked_giftcard.secret if medium.linked_giftcard_id else '',
|
giftcard_secret,
|
||||||
medium.notes,
|
medium.notes,
|
||||||
]
|
]
|
||||||
yield row
|
|
||||||
|
|
||||||
def get_filename(self):
|
def get_filename(self):
|
||||||
return f'{self.organizer.slug}_media'
|
return f'{self.organizer.slug}_media'
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
@@ -47,9 +48,7 @@ from django.conf import settings
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.core.validators import (
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
MaxValueValidator, MinValueValidator, RegexValidator,
|
|
||||||
)
|
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
from django.forms import Select, widgets
|
from django.forms import Select, widgets
|
||||||
from django.forms.widgets import FILE_INPUT_CONTRADICTION
|
from django.forms.widgets import FILE_INPUT_CONTRADICTION
|
||||||
@@ -220,20 +219,6 @@ class NamePartsFormField(forms.MultiValueField):
|
|||||||
defaults = {
|
defaults = {
|
||||||
'widget': self.widget,
|
'widget': self.widget,
|
||||||
'max_length': kwargs.pop('max_length', None),
|
'max_length': kwargs.pop('max_length', None),
|
||||||
'validators': [
|
|
||||||
RegexValidator(
|
|
||||||
# The following characters should never appear in a name anywhere of
|
|
||||||
# the world. However, they commonly appear in inputs generated by spam
|
|
||||||
# bots.
|
|
||||||
r'^[^$€/%§{}<>~]*$',
|
|
||||||
message=_('Please do not use special characters in names.')
|
|
||||||
),
|
|
||||||
RegexValidator(
|
|
||||||
URL_RE,
|
|
||||||
inverse_match=True,
|
|
||||||
message=_('Please do not use special characters in names.')
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
self.max_length = defaults['max_length']
|
self.max_length = defaults['max_length']
|
||||||
self.scheme_name = kwargs.pop('scheme')
|
self.scheme_name = kwargs.pop('scheme')
|
||||||
@@ -255,7 +240,6 @@ class NamePartsFormField(forms.MultiValueField):
|
|||||||
if fname == 'title' and self.scheme_titles:
|
if fname == 'title' and self.scheme_titles:
|
||||||
d = dict(defaults)
|
d = dict(defaults)
|
||||||
d.pop('max_length', None)
|
d.pop('max_length', None)
|
||||||
d.pop('validators', None)
|
|
||||||
field = forms.ChoiceField(
|
field = forms.ChoiceField(
|
||||||
**d,
|
**d,
|
||||||
choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]]
|
choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]]
|
||||||
@@ -264,7 +248,6 @@ class NamePartsFormField(forms.MultiValueField):
|
|||||||
elif fname == 'salutation':
|
elif fname == 'salutation':
|
||||||
d = dict(defaults)
|
d = dict(defaults)
|
||||||
d.pop('max_length', None)
|
d.pop('max_length', None)
|
||||||
d.pop('validators', None)
|
|
||||||
field = forms.ChoiceField(
|
field = forms.ChoiceField(
|
||||||
**d,
|
**d,
|
||||||
choices=[
|
choices=[
|
||||||
@@ -296,6 +279,37 @@ class NamePartsFormField(forms.MultiValueField):
|
|||||||
if sum(len(v) for v in value.values() if v) > (self.max_length or 250):
|
if sum(len(v) for v in value.values() if v) > (self.max_length or 250):
|
||||||
raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length')
|
raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length')
|
||||||
|
|
||||||
|
for fname, label, size in self.scheme['fields']:
|
||||||
|
if fname == 'salutation' or (fname == 'title' and self.scheme_titles):
|
||||||
|
continue
|
||||||
|
v = value.get(fname)
|
||||||
|
if not v:
|
||||||
|
continue
|
||||||
|
special_chars = re.findall('[$€/%§{}<>~]', v)
|
||||||
|
if special_chars:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_('The field "%(label)s" may not contain special characters such as "%(chars)s".'),
|
||||||
|
code='name_special_chars',
|
||||||
|
params={
|
||||||
|
"label": label,
|
||||||
|
"chars": "".join(special_chars),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
# URL_RE checks for valid domain names, including one special TLD med, which can be part of a title
|
||||||
|
if ".med" in v:
|
||||||
|
v = v.replace(".med", ". med")
|
||||||
|
value[fname] = v
|
||||||
|
url_matched = URL_RE.search(v)
|
||||||
|
if url_matched:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_('The field "%(label)s" may not contain an URL (%(url)s).'),
|
||||||
|
code='url_in_title',
|
||||||
|
params={
|
||||||
|
"label": label,
|
||||||
|
"url": url_matched.group(0),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if value.get("salutation") == "empty":
|
if value.get("salutation") == "empty":
|
||||||
value["salutation"] = ""
|
value["salutation"] = ""
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#
|
||||||
|
# This file is part of pretix (Community Edition).
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
|
# Copyright (C) 2020-today pretix 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""This command supersedes the Django-inbuilt runserver command.
|
||||||
|
|
||||||
|
It runs the local frontend server, if node is installed and the setting
|
||||||
|
is set.
|
||||||
|
"""
|
||||||
|
import atexit
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.staticfiles.management.commands.runserver import (
|
||||||
|
Command as Parent,
|
||||||
|
)
|
||||||
|
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV
|
||||||
|
|
||||||
|
|
||||||
|
class Command(Parent):
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
# Only start Vite in the non-main process of the autoreloader
|
||||||
|
if settings.VITE_DEV_MODE and os.environ.get(DJANGO_AUTORELOAD_ENV) != "true":
|
||||||
|
# Start the vite server in the background
|
||||||
|
vite_server = subprocess.Popen(
|
||||||
|
["npm", "run", "dev:control"],
|
||||||
|
cwd=Path(__file__).parent.parent.parent.parent.parent
|
||||||
|
)
|
||||||
|
|
||||||
|
def cleanup():
|
||||||
|
vite_server.terminate()
|
||||||
|
try:
|
||||||
|
vite_server.wait(timeout=5)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
vite_server.kill()
|
||||||
|
|
||||||
|
atexit.register(cleanup)
|
||||||
|
|
||||||
|
super().handle(*args, **options)
|
||||||
@@ -281,7 +281,7 @@ class SecurityMiddleware(MiddlewareMixin):
|
|||||||
|
|
||||||
h = {
|
h = {
|
||||||
'default-src': ["{static}"],
|
'default-src': ["{static}"],
|
||||||
'script-src': ['{static}'],
|
'script-src': ["{static}"],
|
||||||
'object-src': ["'none'"],
|
'object-src': ["'none'"],
|
||||||
'frame-src': ['{static}'],
|
'frame-src': ['{static}'],
|
||||||
'style-src': ["{static}", "{media}"],
|
'style-src': ["{static}", "{media}"],
|
||||||
@@ -295,6 +295,18 @@ class SecurityMiddleware(MiddlewareMixin):
|
|||||||
# this. However, we'll restrict it to HTTPS.
|
# this. However, we'll restrict it to HTTPS.
|
||||||
'form-action': ["{dynamic}", "https:"] + (['http:'] if settings.SITE_URL.startswith('http://') else []),
|
'form-action': ["{dynamic}", "https:"] + (['http:'] if settings.SITE_URL.startswith('http://') else []),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if settings.VITE_DEV_MODE:
|
||||||
|
h['script-src'] += ["http://localhost:5173", "ws://localhost:5173"]
|
||||||
|
h['style-src'] += ["'unsafe-inline'"]
|
||||||
|
h['connect-src'] += ["http://localhost:5173", "ws://localhost:5173"]
|
||||||
|
|
||||||
|
if hasattr(request, 'csp_nonce'):
|
||||||
|
nonce = f"'nonce-{request.csp_nonce}'"
|
||||||
|
h['script-src'].append(nonce)
|
||||||
|
if not settings.VITE_DEV_MODE:
|
||||||
|
# can't have 'unsafe-inline' and nonce at the same time
|
||||||
|
h['style-src'].append(nonce)
|
||||||
# Only include pay.google.com for wallet detection purposes on the Payment selection page
|
# Only include pay.google.com for wallet detection purposes on the Payment selection page
|
||||||
if (
|
if (
|
||||||
url.url_name == "event.order.pay.change" or
|
url.url_name == "event.order.pay.change" or
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 4.2.26 on 2025-11-24 11:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("pretixbase", "0299_itemprogramtime_location"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="reusablemedium",
|
||||||
|
name="claim_token",
|
||||||
|
field=models.CharField(max_length=200, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="reusablemedium",
|
||||||
|
name="label",
|
||||||
|
field=models.CharField(max_length=200, null=True),
|
||||||
|
),
|
||||||
|
# use temporary related_name "linked_mediums" for ManyToManyField, so we can migrate existing data
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="reusablemedium",
|
||||||
|
name="linked_orderpositions",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
related_name="linked_mediums", to="pretixbase.orderposition"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunSQL(
|
||||||
|
sql="INSERT INTO pretixbase_reusablemedium_linked_orderpositions (reusablemedium_id, orderposition_id) SELECT id, linked_orderposition_id FROM pretixbase_reusablemedium WHERE linked_orderposition_id IS NOT NULL;",
|
||||||
|
reverse_sql="DELETE FROM pretixbase_reusablemedium_linked_orderpositions;",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Generated by Django 4.2.26 on 2025-11-24 11:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
ReusableMedium = apps.get_model('pretixbase', 'ReusableMedium')
|
||||||
|
|
||||||
|
qs = ReusableMedium.linked_orderpositions.through.objects
|
||||||
|
objs = []
|
||||||
|
# get last added orderposition from linked_orderpositions
|
||||||
|
for rm_id, op_id in qs.filter(id__in=qs.values("reusablemedium_id").annotate(max_id=models.Max('id')).values('max_id')).values_list("reusablemedium_id", "orderposition_id"):
|
||||||
|
obj = ReusableMedium(
|
||||||
|
id=rm_id,
|
||||||
|
linked_orderposition_id=op_id,
|
||||||
|
)
|
||||||
|
objs.append(obj)
|
||||||
|
|
||||||
|
ReusableMedium.objects.bulk_update(objs, ['linked_orderposition_id'])
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("pretixbase", "0300_add_reusablemedium_label"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
# according to the docs, UPDATE FROM should run similarly on sqlite and postgres, but I could not get it to work
|
||||||
|
# so roll back the data migration with code before deleting data from through-table in 0297
|
||||||
|
migrations.RunPython(migrations.RunPython.noop, reverse),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="reusablemedium",
|
||||||
|
name="linked_orderposition",
|
||||||
|
),
|
||||||
|
# change related_name for new ManyToManyField to previously used linked_media
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="reusablemedium",
|
||||||
|
name="linked_orderpositions",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
related_name="linked_media", to="pretixbase.orderposition"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -442,7 +442,7 @@ class AttendeeState(ImportColumn):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def verbose_name(self):
|
def verbose_name(self):
|
||||||
return _('Attendee address') + ': ' + _('State')
|
return _('Attendee address') + ': ' + pgettext('address', 'State')
|
||||||
|
|
||||||
def clean(self, value, previous_values):
|
def clean(self, value, previous_values):
|
||||||
if value:
|
if value:
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class LoggingMixin:
|
|||||||
elif isinstance(self, Event):
|
elif isinstance(self, Event):
|
||||||
event = self
|
event = self
|
||||||
organizer_id = self.organizer_id
|
organizer_id = self.organizer_id
|
||||||
elif hasattr(self, 'event'):
|
elif hasattr(self, 'event') and self.event:
|
||||||
event = self.event
|
event = self.event
|
||||||
organizer_id = self.event.organizer_id
|
organizer_id = self.event.organizer_id
|
||||||
elif hasattr(self, 'organizer_id'):
|
elif hasattr(self, 'organizer_id'):
|
||||||
|
|||||||
@@ -72,6 +72,16 @@ class ReusableMedium(LoggedModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
verbose_name=pgettext_lazy('reusable_medium', 'Identifier'),
|
verbose_name=pgettext_lazy('reusable_medium', 'Identifier'),
|
||||||
)
|
)
|
||||||
|
claim_token = models.CharField(
|
||||||
|
max_length=200,
|
||||||
|
verbose_name=pgettext_lazy('reusable_medium', 'Claim token'),
|
||||||
|
null=True, blank=True
|
||||||
|
)
|
||||||
|
label = models.CharField(
|
||||||
|
max_length=200,
|
||||||
|
verbose_name=pgettext_lazy('reusable_medium', 'Label'),
|
||||||
|
null=True, blank=True
|
||||||
|
)
|
||||||
|
|
||||||
active = models.BooleanField(
|
active = models.BooleanField(
|
||||||
verbose_name=_('Active'),
|
verbose_name=_('Active'),
|
||||||
@@ -89,12 +99,14 @@ class ReusableMedium(LoggedModel):
|
|||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
verbose_name=_('Customer account'),
|
verbose_name=_('Customer account'),
|
||||||
)
|
)
|
||||||
linked_orderposition = models.ForeignKey(
|
linked_orderpositions = models.ManyToManyField(
|
||||||
OrderPosition,
|
OrderPosition,
|
||||||
null=True, blank=True,
|
|
||||||
related_name='linked_media',
|
related_name='linked_media',
|
||||||
on_delete=models.SET_NULL,
|
verbose_name=_('Linked tickets'),
|
||||||
verbose_name=_('Linked ticket'),
|
help_text=_(
|
||||||
|
'If you link to more than one ticket, make sure there is no overlap in validity. '
|
||||||
|
'If multiple tickets are valid at once, this will lead to failed check-ins.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
linked_giftcard = models.ForeignKey(
|
linked_giftcard = models.ForeignKey(
|
||||||
GiftCard,
|
GiftCard,
|
||||||
|
|||||||
@@ -3515,8 +3515,8 @@ def signal_listener_issue_media(sender: Event, order: Order, **kwargs):
|
|||||||
identifier=mt.generate_identifier(sender.organizer),
|
identifier=mt.generate_identifier(sender.organizer),
|
||||||
active=True,
|
active=True,
|
||||||
customer=order.customer,
|
customer=order.customer,
|
||||||
linked_orderposition=p,
|
|
||||||
)
|
)
|
||||||
|
rm.linked_orderpositions.add(p)
|
||||||
rm.log_action(
|
rm.log_action(
|
||||||
'pretix.reusable_medium.created',
|
'pretix.reusable_medium.created',
|
||||||
data={
|
data={
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -20,6 +20,6 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
|
||||||
<script src="{% static "pretixbase/js/errors.js" %}"></script>
|
<script src="{% static "pretixbase/js/errors.js" %}"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -55,10 +55,12 @@
|
|||||||
{% trans "You receive these emails based on your notification settings." %}<br>
|
{% trans "You receive these emails based on your notification settings." %}<br>
|
||||||
<a href="{{ settings_url }}">
|
<a href="{{ settings_url }}">
|
||||||
{% trans "Click here to view and change your notification settings" %}
|
{% trans "Click here to view and change your notification settings" %}
|
||||||
</a><br>
|
|
||||||
<a href="{{ disable_url }}">
|
|
||||||
{% trans "Click here disable all notifications immediately." %}
|
|
||||||
</a>
|
</a>
|
||||||
|
{% if disable_url %}<br>
|
||||||
|
<a href="{{ disable_url }}">
|
||||||
|
{% trans "Click here disable all notifications immediately." %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<!--[if gte mso 9]>
|
<!--[if gte mso 9]>
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
|
|||||||
@@ -14,5 +14,6 @@
|
|||||||
{% trans "You receive these emails based on your notification settings." %}
|
{% trans "You receive these emails based on your notification settings." %}
|
||||||
{% trans "Click here to view and change your notification settings:" %}
|
{% trans "Click here to view and change your notification settings:" %}
|
||||||
{{ settings_url }}
|
{{ settings_url }}
|
||||||
{% trans "Click here disable all notifications immediately:" %}
|
{% if disable_url %}{% trans "Click here disable all notifications immediately:" %}
|
||||||
{{ disable_url }}
|
{{ disable_url }}
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# This file is part of pretix (Community Edition).
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
|
# Copyright (C) 2020-today pretix 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 import template
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def human_readable_locale(value):
|
||||||
|
if not value:
|
||||||
|
return ''
|
||||||
|
return dict(settings.LANGUAGES).get(value, '')
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
#
|
||||||
|
# This file is part of pretix (Community Edition).
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
|
# Copyright (C) 2020-today pretix 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
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import secrets
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
import importlib_metadata as metadata
|
||||||
|
from django import template
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
_MANIFEST = {}
|
||||||
|
# TODO more os.path.join ?
|
||||||
|
MANIFEST_PATH = settings.STATIC_ROOT + "/vite/control/.vite/manifest.json"
|
||||||
|
MANIFEST_BASE = "vite/control/"
|
||||||
|
|
||||||
|
# entry_name -> {"manifest_entry": {...}, "url_base": "..."}
|
||||||
|
_PLUGIN_REGISTRY = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _discover_plugin_manifests():
|
||||||
|
"""Discover plugin vite manifests at startup.
|
||||||
|
|
||||||
|
Scans installed pretix plugins for a .vite/manifest.json inside a static.dist
|
||||||
|
directory. Only non-editable (wheel) plugins are expected to ship pre-built
|
||||||
|
assets; editable plugins are served through the Vite dev server.
|
||||||
|
"""
|
||||||
|
for ep in metadata.entry_points(group='pretix.plugin'):
|
||||||
|
dist = ep.dist
|
||||||
|
if not dist or not dist.files:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
url_info = json.loads(dist.read_text('direct_url.json') or '{}')
|
||||||
|
if url_info.get('dir_info', {}).get('editable', False):
|
||||||
|
continue # editable plugins are served via vite dev server
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Find .vite/manifest.json inside a /static/ directory
|
||||||
|
try:
|
||||||
|
manifest_rel = None
|
||||||
|
for f in dist.files:
|
||||||
|
if f.name == 'manifest.json' and '/static/' in str(f) and '/.vite/' in str(f):
|
||||||
|
manifest_rel = f
|
||||||
|
break
|
||||||
|
|
||||||
|
if not manifest_rel:
|
||||||
|
continue
|
||||||
|
|
||||||
|
manifest_path = pathlib.Path(str(dist.locate_file(manifest_rel)))
|
||||||
|
if not manifest_path.exists():
|
||||||
|
continue
|
||||||
|
|
||||||
|
plugin_manifest = json.loads(manifest_path.read_text())
|
||||||
|
|
||||||
|
url_base = re.search(r'/static/(.+?)/\.vite/', str(manifest_rel)).group(1) + '/'
|
||||||
|
|
||||||
|
for _key, entry in plugin_manifest.items():
|
||||||
|
if entry.get('isEntry') and 'name' in entry:
|
||||||
|
_PLUGIN_REGISTRY[entry['name']] = {
|
||||||
|
'manifest_entry': entry,
|
||||||
|
'url_base': url_base,
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
LOGGER.warning(f"Failed to discover vite manifest for plugin {ep.name}", exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Load core manifest
|
||||||
|
if not settings.VITE_DEV_MODE and not settings.VITE_IGNORE:
|
||||||
|
try:
|
||||||
|
with open(MANIFEST_PATH) as fp:
|
||||||
|
_MANIFEST = json.load(fp)
|
||||||
|
except Exception as e:
|
||||||
|
LOGGER.warning(f"Error reading vite manifest at {MANIFEST_PATH}: {str(e)}")
|
||||||
|
|
||||||
|
# Discover plugin manifests
|
||||||
|
if not settings.VITE_IGNORE:
|
||||||
|
_discover_plugin_manifests()
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_script_tag(path, attrs, src=None):
|
||||||
|
all_attrs = " ".join(f'{key}="{value}"' for key, value in attrs.items())
|
||||||
|
if src is None:
|
||||||
|
if settings.VITE_DEV_MODE:
|
||||||
|
src = urljoin(settings.VITE_DEV_SERVER, path)
|
||||||
|
else:
|
||||||
|
src = urljoin(settings.STATIC_URL, path)
|
||||||
|
return f'<script {all_attrs} src="{src}"></script>'
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_css_tags(asset, already_processed=None):
|
||||||
|
"""Recursively builds all CSS tags used in a given asset from the core manifest."""
|
||||||
|
tags = []
|
||||||
|
manifest_entry = _MANIFEST[asset]
|
||||||
|
if already_processed is None:
|
||||||
|
already_processed = []
|
||||||
|
|
||||||
|
if "css" in manifest_entry:
|
||||||
|
for css_path in manifest_entry["css"]:
|
||||||
|
if css_path not in already_processed:
|
||||||
|
full_path = urljoin(settings.STATIC_URL, MANIFEST_BASE + css_path)
|
||||||
|
tags.append(f'<link rel="stylesheet" href="{full_path}" />')
|
||||||
|
already_processed.append(css_path)
|
||||||
|
|
||||||
|
if "imports" in manifest_entry:
|
||||||
|
for import_path in manifest_entry["imports"]:
|
||||||
|
tags += _generate_css_tags(import_path, already_processed)
|
||||||
|
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_plugin_css_tags(manifest_entry, url_base):
|
||||||
|
"""Build CSS tags for a plugin manifest entry."""
|
||||||
|
tags = []
|
||||||
|
if "css" in manifest_entry:
|
||||||
|
for css_path in manifest_entry["css"]:
|
||||||
|
full_path = urljoin(settings.STATIC_URL, url_base + css_path)
|
||||||
|
tags.append(f'<link rel="stylesheet" href="{full_path}" />')
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
@mark_safe
|
||||||
|
def vite_asset(path):
|
||||||
|
"""
|
||||||
|
Generates one <script> tag and <link> tags for each of the CSS dependencies.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not path:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Check plugin registry (non-editable plugins with pre-built assets)
|
||||||
|
if path in _PLUGIN_REGISTRY:
|
||||||
|
info = _PLUGIN_REGISTRY[path]
|
||||||
|
entry = info['manifest_entry']
|
||||||
|
url_base = info['url_base']
|
||||||
|
tags = _generate_plugin_css_tags(entry, url_base)
|
||||||
|
# Always use STATIC_URL for pre-built plugin assets, even in dev mode
|
||||||
|
src = urljoin(settings.STATIC_URL, url_base + entry["file"])
|
||||||
|
tags.append(_generate_script_tag(path, {"type": "module", "crossorigin": ""}, src=src))
|
||||||
|
return "".join(tags)
|
||||||
|
|
||||||
|
# Dev mode: editable plugins and core entries go through the vite dev server
|
||||||
|
if settings.VITE_DEV_MODE:
|
||||||
|
return _generate_script_tag(path, {"type": "module"})
|
||||||
|
|
||||||
|
# Prod mode
|
||||||
|
manifest_entry = _MANIFEST.get(path)
|
||||||
|
if not manifest_entry:
|
||||||
|
raise RuntimeError(f"Cannot find {path} in Vite manifest at {MANIFEST_PATH}")
|
||||||
|
|
||||||
|
tags = _generate_css_tags(path)
|
||||||
|
tags.append(
|
||||||
|
_generate_script_tag(
|
||||||
|
MANIFEST_BASE + manifest_entry["file"], {"type": "module", "crossorigin": ""}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return "".join(tags)
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
@mark_safe
|
||||||
|
def vite_hmr():
|
||||||
|
if not settings.VITE_DEV_MODE:
|
||||||
|
return ""
|
||||||
|
return _generate_script_tag("@vite/client", {"type": "module"})
|
||||||
|
|
||||||
|
|
||||||
|
_dev_importmap_cache = None
|
||||||
|
|
||||||
|
|
||||||
|
def _get_dev_importmap():
|
||||||
|
"""Fetch the shared-dep import map from the Vite dev server. Cached after first call."""
|
||||||
|
global _dev_importmap_cache
|
||||||
|
if _dev_importmap_cache is not None:
|
||||||
|
return _dev_importmap_cache
|
||||||
|
try:
|
||||||
|
url = urljoin(settings.VITE_DEV_SERVER, "/__pretix_importmap")
|
||||||
|
raw = json.loads(urlopen(url, timeout=2).read())
|
||||||
|
_dev_importmap_cache = {
|
||||||
|
dep: urljoin(settings.VITE_DEV_SERVER, dep_path)
|
||||||
|
for dep, dep_path in raw.items()
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
LOGGER.warning("Failed to fetch import map from Vite dev server")
|
||||||
|
_dev_importmap_cache = {}
|
||||||
|
return _dev_importmap_cache
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
@mark_safe
|
||||||
|
def vite_importmap(context):
|
||||||
|
"""Emit an import map so pre-built plugin assets can resolve shared dependencies like vue."""
|
||||||
|
imports = {}
|
||||||
|
|
||||||
|
if settings.VITE_DEV_MODE:
|
||||||
|
# Fetch the import map from the Vite dev server (served by sharedDepsPlugin)
|
||||||
|
imports.update(_get_dev_importmap())
|
||||||
|
else:
|
||||||
|
# Discover all _vendor/* entries from the core manifest
|
||||||
|
for _key, entry in _MANIFEST.items():
|
||||||
|
name = entry.get("name", "")
|
||||||
|
if name.startswith("_vendor/"):
|
||||||
|
bare_specifier = name[len("_vendor/"):]
|
||||||
|
imports[bare_specifier] = urljoin(settings.STATIC_URL, MANIFEST_BASE + entry["file"])
|
||||||
|
|
||||||
|
if not imports:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Generate a nonce and store it on the request so the CSP middleware can allow it
|
||||||
|
nonce = secrets.token_urlsafe(16)
|
||||||
|
request = context.get('request')
|
||||||
|
if request:
|
||||||
|
request.csp_nonce = nonce
|
||||||
|
|
||||||
|
return f'<script type="importmap" nonce="{nonce}">{json.dumps({"imports": imports})}</script>'
|
||||||
@@ -24,10 +24,12 @@ import calendar
|
|||||||
from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rrulestr
|
from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rrulestr
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import RegexValidator, validate_email
|
||||||
from django.utils.deconstruct import deconstructible
|
from django.utils.deconstruct import deconstructible
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from pretix.base.templatetags.rich_text import URL_RE
|
||||||
|
|
||||||
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
|
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
|
||||||
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
|
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
#
|
#
|
||||||
@@ -113,6 +115,33 @@ def multimail_validate(val):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class RegexValidatorInverseMatchAndParam(RegexValidator):
|
||||||
|
inverse_match = True
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
regex_matches = self.regex.search(str(value))
|
||||||
|
if regex_matches:
|
||||||
|
raise ValidationError(
|
||||||
|
self.message,
|
||||||
|
code=self.code,
|
||||||
|
params={
|
||||||
|
"value": value,
|
||||||
|
"match": regex_matches.group(0) if regex_matches else "",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NoUrlValidator(RegexValidatorInverseMatchAndParam):
|
||||||
|
regex = URL_RE
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
if not kwargs.get("message"):
|
||||||
|
kwargs["message"] = _('You entered an URL, which is not allowed. Please remove %(match)s from your input.')
|
||||||
|
if not kwargs.get("code"):
|
||||||
|
kwargs["code"] = "contains_url"
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RRuleValidator:
|
class RRuleValidator:
|
||||||
def __init__(self, enforce_simple=False):
|
def __init__(self, enforce_simple=False):
|
||||||
self.enforce_simple = enforce_simple
|
self.enforce_simple = enforce_simple
|
||||||
|
|||||||
@@ -461,3 +461,31 @@ class SalesChannelCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
|||||||
**super().create_option(name, value, label, selected, index, subindex, attrs),
|
**super().create_option(name, value, label, selected, index, subindex, attrs),
|
||||||
"plugin_missing": plugin and plugin not in self.event.get_plugins(),
|
"plugin_missing": plugin and plugin not in self.event.get_plugins(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ModelChoiceIteratorWithNone(forms.models.ModelChoiceIterator):
|
||||||
|
# see django.forms.models.ModelChoiceIterator for original implementation
|
||||||
|
def __iter__(self):
|
||||||
|
if self.field.empty_label is not None:
|
||||||
|
yield ("", self.field.empty_label)
|
||||||
|
if self.field.none_label is not None:
|
||||||
|
yield ("_none", self.field.none_label)
|
||||||
|
queryset = self.queryset
|
||||||
|
# Can't use iterator() when queryset uses prefetch_related()
|
||||||
|
if not queryset._prefetch_related_lookups:
|
||||||
|
queryset = queryset.iterator()
|
||||||
|
for obj in queryset:
|
||||||
|
yield self.choice(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class ModelChoiceFieldWithNone(forms.ModelChoiceField):
|
||||||
|
iterator = ModelChoiceIteratorWithNone
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.none_label = kwargs.pop("none_label", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
if value == "_none":
|
||||||
|
return value
|
||||||
|
return super().to_python(value)
|
||||||
|
|||||||
@@ -1871,7 +1871,7 @@ class ReusableMediaFilterForm(FilterForm):
|
|||||||
Q(identifier__icontains=query)
|
Q(identifier__icontains=query)
|
||||||
| Q(customer__identifier__icontains=query)
|
| Q(customer__identifier__icontains=query)
|
||||||
| Q(customer__external_identifier__istartswith=query)
|
| Q(customer__external_identifier__istartswith=query)
|
||||||
| Q(linked_orderposition__order__code__icontains=query)
|
| Q(linked_orderpositions__order__code__icontains=query)
|
||||||
| Q(linked_giftcard__secret__icontains=query)
|
| Q(linked_giftcard__secret__icontains=query)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,13 @@ class GlobalSettingsForm(SettingsForm):
|
|||||||
help_text=_("Will be served at {domain}/.well-known/apple-developer-merchantid-domain-association").format(
|
help_text=_("Will be served at {domain}/.well-known/apple-developer-merchantid-domain-association").format(
|
||||||
domain=settings.SITE_URL
|
domain=settings.SITE_URL
|
||||||
)
|
)
|
||||||
|
)),
|
||||||
|
('widget_vite_origins', forms.CharField(
|
||||||
|
widget=forms.Textarea(attrs={'rows': '3'}),
|
||||||
|
required=False,
|
||||||
|
# Not translated on purpose, this is a temporary feature and contains too many special case words
|
||||||
|
label="Vite widget origins",
|
||||||
|
help_text="One origin per line (e.g. https://example.com). Requests from these origins will be served the new vite-based widget.",
|
||||||
))
|
))
|
||||||
])
|
])
|
||||||
responses = register_global_settings.send(self)
|
responses = register_global_settings.send(self)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ from pretix.control.forms import ExtFileField, SplitDateTimeField
|
|||||||
from pretix.control.forms.event import (
|
from pretix.control.forms.event import (
|
||||||
SafeEventMultipleChoiceField, multimail_validate,
|
SafeEventMultipleChoiceField, multimail_validate,
|
||||||
)
|
)
|
||||||
from pretix.control.forms.widgets import Select2
|
from pretix.control.forms.widgets import Select2, Select2Multiple
|
||||||
from pretix.multidomain.models import KnownDomain
|
from pretix.multidomain.models import KnownDomain
|
||||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||||
|
|
||||||
@@ -249,6 +249,15 @@ class SafeOrderPositionChoiceField(forms.ModelChoiceField):
|
|||||||
return f'{op.order.code}-{op.positionid} ({str(op.item) + ((" - " + str(op.variation)) if op.variation else "")})'
|
return f'{op.order.code}-{op.positionid} ({str(op.item) + ((" - " + str(op.variation)) if op.variation else "")})'
|
||||||
|
|
||||||
|
|
||||||
|
class SafeOrderPositionMultipleChoiceField(forms.ModelMultipleChoiceField):
|
||||||
|
def __init__(self, queryset, **kwargs):
|
||||||
|
queryset = queryset.model.all.none()
|
||||||
|
super().__init__(queryset, **kwargs)
|
||||||
|
|
||||||
|
def label_from_instance(self, op):
|
||||||
|
return f'{op.order.code}-{op.positionid} ({str(op.item) + ((" - " + str(op.variation)) if op.variation else "")})'
|
||||||
|
|
||||||
|
|
||||||
class EventMetaPropertyForm(I18nModelForm):
|
class EventMetaPropertyForm(I18nModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = EventMetaProperty
|
model = EventMetaProperty
|
||||||
@@ -963,12 +972,12 @@ class ReusableMediumUpdateForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReusableMedium
|
model = ReusableMedium
|
||||||
fields = ['active', 'expires', 'customer', 'linked_giftcard', 'linked_orderposition', 'notes']
|
fields = ['active', 'expires', 'customer', 'linked_giftcard', 'linked_orderpositions', 'notes']
|
||||||
field_classes = {
|
field_classes = {
|
||||||
'expires': SplitDateTimeField,
|
'expires': SplitDateTimeField,
|
||||||
'customer': SafeModelChoiceField,
|
'customer': SafeModelChoiceField,
|
||||||
'linked_giftcard': SafeModelChoiceField,
|
'linked_giftcard': SafeModelChoiceField,
|
||||||
'linked_orderposition': SafeOrderPositionChoiceField,
|
'linked_orderpositions': SafeOrderPositionMultipleChoiceField,
|
||||||
}
|
}
|
||||||
widgets = {
|
widgets = {
|
||||||
'expires': SplitDateTimePickerWidget,
|
'expires': SplitDateTimePickerWidget,
|
||||||
@@ -978,8 +987,8 @@ class ReusableMediumUpdateForm(forms.ModelForm):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
organizer = self.instance.organizer
|
organizer = self.instance.organizer
|
||||||
|
|
||||||
self.fields['linked_orderposition'].queryset = OrderPosition.all.filter(order__event__organizer=organizer).all()
|
self.fields['linked_orderpositions'].queryset = OrderPosition.all.filter(order__event__organizer=organizer).all()
|
||||||
self.fields['linked_orderposition'].widget = Select2(
|
self.fields['linked_orderpositions'].widget = Select2Multiple(
|
||||||
attrs={
|
attrs={
|
||||||
'data-model-select2': 'generic',
|
'data-model-select2': 'generic',
|
||||||
'data-select2-url': reverse('control:organizer.ticket_select2', kwargs={
|
'data-select2-url': reverse('control:organizer.ticket_select2', kwargs={
|
||||||
@@ -987,8 +996,8 @@ class ReusableMediumUpdateForm(forms.ModelForm):
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.fields['linked_orderposition'].widget.choices = self.fields['linked_orderposition'].choices
|
self.fields['linked_orderpositions'].widget.choices = self.fields['linked_orderpositions'].choices
|
||||||
self.fields['linked_orderposition'].required = False
|
self.fields['linked_orderpositions'].required = False
|
||||||
|
|
||||||
self.fields['linked_giftcard'].queryset = organizer.issued_gift_cards.all()
|
self.fields['linked_giftcard'].queryset = organizer.issued_gift_cards.all()
|
||||||
self.fields['linked_giftcard'].widget = Select2(
|
self.fields['linked_giftcard'].widget = Select2(
|
||||||
@@ -1042,12 +1051,12 @@ class ReusableMediumCreateForm(ReusableMediumUpdateForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReusableMedium
|
model = ReusableMedium
|
||||||
fields = ['active', 'type', 'identifier', 'expires', 'linked_orderposition', 'linked_giftcard', 'customer', 'notes']
|
fields = ['active', 'type', 'identifier', 'expires', 'linked_orderpositions', 'linked_giftcard', 'customer', 'notes']
|
||||||
field_classes = {
|
field_classes = {
|
||||||
'expires': SplitDateTimeField,
|
'expires': SplitDateTimeField,
|
||||||
'customer': SafeModelChoiceField,
|
'customer': SafeModelChoiceField,
|
||||||
'linked_giftcard': SafeModelChoiceField,
|
'linked_giftcard': SafeModelChoiceField,
|
||||||
'linked_orderposition': SafeOrderPositionChoiceField,
|
'linked_orderpositions': SafeOrderPositionMultipleChoiceField,
|
||||||
}
|
}
|
||||||
widgets = {
|
widgets = {
|
||||||
'expires': SplitDateTimePickerWidget,
|
'expires': SplitDateTimePickerWidget,
|
||||||
|
|||||||
@@ -29,17 +29,30 @@ class Select2Mixin:
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def options(self, name, value, attrs=None):
|
def options(self, name, value, attrs=None):
|
||||||
if value and value[0]:
|
if not value or not value[0]:
|
||||||
for i, selected in enumerate(self.choices.queryset.filter(pk__in=value)):
|
return
|
||||||
yield self.create_option(
|
has_none = "_none" in value
|
||||||
None,
|
if has_none:
|
||||||
self.choices.field.prepare_value(selected),
|
value = [v for v in value if v != "_none"]
|
||||||
self.choices.field.label_from_instance(selected),
|
yield self.create_option(
|
||||||
True,
|
None,
|
||||||
i,
|
"_none",
|
||||||
subindex=None,
|
self.choices.field.none_label,
|
||||||
attrs=attrs
|
True,
|
||||||
)
|
0,
|
||||||
|
subindex=None,
|
||||||
|
attrs=attrs
|
||||||
|
)
|
||||||
|
for i, selected in enumerate(self.choices.queryset.filter(pk__in=value)):
|
||||||
|
yield self.create_option(
|
||||||
|
None,
|
||||||
|
self.choices.field.prepare_value(selected),
|
||||||
|
self.choices.field.label_from_instance(selected),
|
||||||
|
True,
|
||||||
|
i + (1 if has_none else 0),
|
||||||
|
subindex=None,
|
||||||
|
attrs=attrs
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
def optgroups(self, name, value, attrs=None):
|
def optgroups(self, name, value, attrs=None):
|
||||||
|
|||||||
@@ -34,11 +34,11 @@
|
|||||||
# License for the specific language governing permissions and limitations under the License.
|
# License for the specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from datetime import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
import dateutil.parser
|
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.formats import date_format
|
from django.utils.formats import date_format
|
||||||
@@ -248,7 +248,7 @@ class OrderValidFromChanged(OrderChangeLogEntryType):
|
|||||||
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
||||||
return _('The validity start date for position #{posid} has been changed to {value}.').format(
|
return _('The validity start date for position #{posid} has been changed to {value}.').format(
|
||||||
posid=data.get('positionid', '?'),
|
posid=data.get('positionid', '?'),
|
||||||
value=date_format(dateutil.parser.parse(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get(
|
value=date_format(datetime.fromisoformat(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get(
|
||||||
'new_value') else '–'
|
'new_value') else '–'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ class OrderValidUntilChanged(OrderChangeLogEntryType):
|
|||||||
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
||||||
return _('The validity end date for position #{posid} has been changed to {value}.').format(
|
return _('The validity end date for position #{posid} has been changed to {value}.').format(
|
||||||
posid=data.get('positionid', '?'),
|
posid=data.get('positionid', '?'),
|
||||||
value=date_format(dateutil.parser.parse(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get('new_value') else '–'
|
value=date_format(datetime.fromisoformat(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get('new_value') else '–'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ class CheckinErrorLogEntryType(OrderLogEntryType):
|
|||||||
data['posid'] = logentry.parsed_data.get('positionid', '?')
|
data['posid'] = logentry.parsed_data.get('positionid', '?')
|
||||||
|
|
||||||
if 'datetime' in data:
|
if 'datetime' in data:
|
||||||
dt = dateutil.parser.parse(data.get('datetime'))
|
dt = datetime.fromisoformat(data.get('datetime'))
|
||||||
if abs((logentry.datetime - dt).total_seconds()) > 5 or data.get('forced'):
|
if abs((logentry.datetime - dt).total_seconds()) > 5 or data.get('forced'):
|
||||||
if event:
|
if event:
|
||||||
data['datetime'] = date_format(dt.astimezone(event.timezone), "SHORT_DATETIME_FORMAT")
|
data['datetime'] = date_format(dt.astimezone(event.timezone), "SHORT_DATETIME_FORMAT")
|
||||||
@@ -430,7 +430,7 @@ class OrderPrintLogEntryType(OrderLogEntryType):
|
|||||||
return _('Position #{posid} has been printed at {datetime} with type "{type}".').format(
|
return _('Position #{posid} has been printed at {datetime} with type "{type}".').format(
|
||||||
posid=data.get('positionid'),
|
posid=data.get('positionid'),
|
||||||
datetime=date_format(
|
datetime=date_format(
|
||||||
dateutil.parser.parse(data["datetime"]).astimezone(logentry.event.timezone),
|
datetime.fromisoformat(data["datetime"]).astimezone(logentry.event.timezone),
|
||||||
"SHORT_DATETIME_FORMAT"
|
"SHORT_DATETIME_FORMAT"
|
||||||
) if logentry.event else data["datetime"],
|
) if logentry.event else data["datetime"],
|
||||||
type=dict(PrintLog.PRINT_TYPES)[data["type"]],
|
type=dict(PrintLog.PRINT_TYPES)[data["type"]],
|
||||||
@@ -743,6 +743,8 @@ class CoreUserImpersonatedLogEntryType(UserImpersonatedLogEntryType):
|
|||||||
'pretix.reusable_medium.created': _('The reusable medium has been created.'),
|
'pretix.reusable_medium.created': _('The reusable medium has been created.'),
|
||||||
'pretix.reusable_medium.created.auto': _('The reusable medium has been created automatically.'),
|
'pretix.reusable_medium.created.auto': _('The reusable medium has been created automatically.'),
|
||||||
'pretix.reusable_medium.changed': _('The reusable medium has been changed.'),
|
'pretix.reusable_medium.changed': _('The reusable medium has been changed.'),
|
||||||
|
'pretix.reusable_medium.linked_orderposition.added': _('A new ticket has been added to the medium.'),
|
||||||
|
'pretix.reusable_medium.linked_orderposition.removed': _('A ticket has been removed from the medium.'),
|
||||||
'pretix.reusable_medium.linked_orderposition.changed': _('The medium has been connected to a new ticket.'),
|
'pretix.reusable_medium.linked_orderposition.changed': _('The medium has been connected to a new ticket.'),
|
||||||
'pretix.reusable_medium.linked_giftcard.changed': _('The medium has been connected to a new gift card.'),
|
'pretix.reusable_medium.linked_giftcard.changed': _('The medium has been connected to a new gift card.'),
|
||||||
'pretix.email.error': _('Sending of an email has failed.'),
|
'pretix.email.error': _('Sending of an email has failed.'),
|
||||||
@@ -985,7 +987,7 @@ class LegacyCheckinLogEntryType(OrderLogEntryType):
|
|||||||
|
|
||||||
def display(self, logentry, data):
|
def display(self, logentry, data):
|
||||||
# deprecated
|
# deprecated
|
||||||
dt = dateutil.parser.parse(data.get('datetime'))
|
dt = datetime.fromisoformat(data.get('datetime'))
|
||||||
tz = logentry.event.timezone
|
tz = logentry.event.timezone
|
||||||
dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
|
dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
|
||||||
if 'list' in data:
|
if 'list' in data:
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ quota as argument in the ``quota`` keyword argument.
|
|||||||
As with all event plugin signals, the ``sender`` keyword argument will contain the event.
|
As with all event plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
subevent_detail_html = EventPluginSignal()
|
||||||
|
"""
|
||||||
|
Arguments: 'subevent'
|
||||||
|
|
||||||
|
This signal allows you to append HTML to a SubEvent's detail view. You receive the
|
||||||
|
subevent as argument in the ``subevent`` keyword argument.
|
||||||
|
|
||||||
|
As with all event plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
|
"""
|
||||||
|
|
||||||
organizer_edit_tabs = DeprecatedSignal()
|
organizer_edit_tabs = DeprecatedSignal()
|
||||||
"""
|
"""
|
||||||
Arguments: 'organizer', 'request'
|
Arguments: 'organizer', 'request'
|
||||||
@@ -261,6 +271,16 @@ As with all event plugin signals, the ``sender`` keyword argument will contain t
|
|||||||
Additionally, the argument ``order`` and ``request`` are available.
|
Additionally, the argument ``order`` and ``request`` are available.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
order_approve_info = EventPluginSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``order``, ``request``
|
||||||
|
|
||||||
|
This signal is sent out to display additional information on the order approve page
|
||||||
|
|
||||||
|
As with all event plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
|
Additionally, the argument ``order`` and ``request`` are available.
|
||||||
|
"""
|
||||||
|
|
||||||
order_position_buttons = EventPluginSignal()
|
order_position_buttons = EventPluginSignal()
|
||||||
"""
|
"""
|
||||||
Arguments: ``order``, ``position``, ``request``
|
Arguments: ``order``, ``position``, ``request``
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load statici18n %}
|
{% load statici18n %}
|
||||||
|
{% load vite %}
|
||||||
{% load eventsignal %}
|
{% load eventsignal %}
|
||||||
{% load eventurl %}
|
{% load eventurl %}
|
||||||
{% load dialog %}
|
{% load dialog %}
|
||||||
@@ -84,6 +85,7 @@
|
|||||||
<meta name="theme-color" content="#3b1c4a">
|
<meta name="theme-color" content="#3b1c4a">
|
||||||
<meta name="referrer" content="origin">
|
<meta name="referrer" content="origin">
|
||||||
|
|
||||||
|
{% vite_importmap %}
|
||||||
{% block custom_header %}{% endblock %}
|
{% block custom_header %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body data-datetimeformat="{{ js_datetime_format }}" data-timeformat="{{ js_time_format }}"
|
<body data-datetimeformat="{{ js_datetime_format }}" data-timeformat="{{ js_time_format }}"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load compress %}
|
{% load compress %}
|
||||||
|
{% load vite %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% if checkinlist %}
|
{% if checkinlist %}
|
||||||
{% blocktrans with name=checkinlist.name %}Check-in list: {{ name }}{% endblocktrans %}
|
{% blocktrans with name=checkinlist.name %}Check-in list: {{ name }}{% endblocktrans %}
|
||||||
@@ -74,45 +75,8 @@
|
|||||||
{% bootstrap_field form.ignore_in_statistics layout="control" %}
|
{% bootstrap_field form.ignore_in_statistics layout="control" %}
|
||||||
|
|
||||||
<h3>{% trans "Custom check-in rule" %}</h3>
|
<h3>{% trans "Custom check-in rule" %}</h3>
|
||||||
<div id="rules-editor" class="form-inline">
|
<div id="rules-editor">
|
||||||
<div>
|
<!-- Vue app mount point -->
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
|
||||||
<li role="presentation" class="active">
|
|
||||||
<a href="#rules-edit" role="tab" data-toggle="tab">
|
|
||||||
<span class="fa fa-edit"></span>
|
|
||||||
{% trans "Edit" %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a href="#rules-viz" role="tab" data-toggle="tab">
|
|
||||||
<span class="fa fa-eye"></span>
|
|
||||||
{% trans "Visualize" %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<!-- Tab panes -->
|
|
||||||
<div class="tab-content">
|
|
||||||
<div role="tabpanel" class="tab-pane active" id="rules-edit">
|
|
||||||
<checkin-rules-editor></checkin-rules-editor>
|
|
||||||
</div>
|
|
||||||
<div role="tabpanel" class="tab-pane" id="rules-viz">
|
|
||||||
<checkin-rules-visualization></checkin-rules-visualization>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-info" v-if="missingItems.length">
|
|
||||||
<p>
|
|
||||||
{% trans "Your rule always filters by product or variation, but the following products or variations are not contained in any of your rule parts so people with these tickets will not get in:" %}
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li v-for="h in missingItems">{{ "{" }}{h}{{ "}" }}</li>
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
{% trans "Please double-check if this was intentional." %}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="disabled-withoutjs sr-only">
|
<div class="disabled-withoutjs sr-only">
|
||||||
{{ form.rules }}
|
{{ form.rules }}
|
||||||
@@ -125,13 +89,10 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{ items|json_script:"items" }}
|
{% if items %}
|
||||||
|
{{ items|json_script:"items" }}
|
||||||
{% if DEBUG %}
|
|
||||||
<script type="text/javascript" src="{% static "vuejs/vue.js" %}"></script>
|
|
||||||
{% else %}
|
|
||||||
<script type="text/javascript" src="{% static "vuejs/vue.min.js" %}"></script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% compress js %}
|
{% compress js %}
|
||||||
<script type="text/javascript" src="{% static "d3/d3.v6.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3.v6.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "d3/d3-color.v2.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3-color.v2.js" %}"></script>
|
||||||
@@ -144,15 +105,6 @@
|
|||||||
<script type="text/javascript" src="{% static "d3/d3-drag.v2.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3-drag.v2.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "d3/d3-zoom.v2.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3-zoom.v2.js" %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{% compress js %}
|
{% vite_hmr %}
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules/jsonlogic-boolalg.js" %}"></script>
|
{% vite_asset "src/pretix/static/pretixcontrol/js/ui/checkinrules/index.ts" %}
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/datetimefield.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/timefield.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/lookup-select2.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/checkin-rule.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/checkin-rules-editor.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/viz-node.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/checkin-rules-visualization.vue' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules.js" %}"></script>
|
|
||||||
{% endcompress %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
{% load getitem %}
|
{% load getitem %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load compress %}
|
{% load compress %}
|
||||||
|
{% load vite %}
|
||||||
{% block title %}{% trans "Check-in simulator" %}{% endblock %}
|
{% block title %}{% trans "Check-in simulator" %}{% endblock %}
|
||||||
{% block inside %}
|
{% block inside %}
|
||||||
<h1>
|
<h1>
|
||||||
@@ -124,11 +125,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if result.rule_graph %}
|
{% if result.rule_graph %}
|
||||||
<div id="rules-editor" class="form-inline">
|
<div id="rules-editor" class="form-inline">
|
||||||
<div role="tabpanel" class="tab-pane" id="rules-viz">
|
<!-- Vue app mount point -->
|
||||||
<checkin-rules-visualization></checkin-rules-visualization>
|
|
||||||
</div>
|
|
||||||
<textarea id="id_rules" class="sr-only">{{ result.rule_graph|attr_escapejson_dumps }}</textarea>
|
|
||||||
</div>
|
</div>
|
||||||
|
<textarea id="id_rules" class="sr-only">{{ result.rule_graph|attr_escapejson_dumps }}</textarea>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,10 +151,6 @@
|
|||||||
<script type="text/javascript" src="{% static "d3/d3-drag.v2.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3-drag.v2.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "d3/d3-zoom.v2.js" %}"></script>
|
<script type="text/javascript" src="{% static "d3/d3-zoom.v2.js" %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{% compress js %}
|
{% vite_hmr %}
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules/jsonlogic-boolalg.js" %}"></script>
|
{% vite_asset "src/pretix/static/pretixcontrol/js/ui/checkinrules/index.ts" %}
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/viz-node.vue' %}"></script>
|
|
||||||
<script type="text/vue" src="{% static 'pretixcontrol/js/ui/checkinrules/checkin-rules-visualization.vue' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/checkinrules.js" %}"></script>
|
|
||||||
{% endcompress %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -9,23 +9,24 @@
|
|||||||
<h3 class="panel-title">{% trans "Go offline" %}</h3>
|
<h3 class="panel-title">{% trans "Go offline" %}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row panel-body">
|
<div class="row panel-body">
|
||||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
<div class="col-sm-12 col-lg-6">
|
||||||
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
You can take your event offline. Nobody except your team will be able to see or access it any more.
|
You can take your event offline. Nobody except your team will be able to see or access it any more.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</div>
|
</p>
|
||||||
<div class="col-sm-12 col-md-3">
|
</div>
|
||||||
<form action="{% url "control:event.live" event=request.event.slug organizer=request.organizer.slug %}"
|
<form class="col-sm-12 col-lg-6 text-right"
|
||||||
method="post">
|
action="{% url "control:event.live" event=request.event.slug organizer=request.organizer.slug %}"
|
||||||
{% csrf_token %}
|
method="post">
|
||||||
<input type="hidden" name="live" value="false">
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="live" value="false">
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary btn-lg btn-block">
|
<button type="submit" class="btn btn-primary btn-lg">
|
||||||
<span class="fa fa-power-off"></span>
|
<span class="fa fa-power-off"></span>
|
||||||
{% trans "Go offline" %}
|
{% trans "Go offline" %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -34,22 +35,24 @@
|
|||||||
<h3 class="panel-title">{% trans "Cancel event" %}</h3>
|
<h3 class="panel-title">{% trans "Cancel event" %}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row panel-body">
|
<div class="row panel-body">
|
||||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
<div class="col-sm-12 col-lg-6">
|
||||||
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
If you need to call off your event you want to cancel and refund all tickets, you can do so through
|
If you need to call off your event you want to cancel and refund all tickets, you can do so through
|
||||||
this option.
|
this option.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-3 text-center">
|
<div class="col-sm-12 col-lg-6 text-right">
|
||||||
{% if "event:cancel" in request.eventpermset %}
|
<a href="{% url "control:event.cancel" organizer=request.organizer.slug event=request.event.slug %}"
|
||||||
<a href="{% url "control:event.cancel" organizer=request.organizer.slug event=request.event.slug %}"
|
class="btn btn-danger btn-lg pull-right {% if "event:cancel" not in request.eventpermset %}disabled{% endif %}">
|
||||||
class="btn btn-danger btn-block btn-lg">
|
<span class="fa fa-ban"></span>
|
||||||
<span class="fa fa-ban"></span>
|
{% if "event:cancel" in request.eventpermset %}
|
||||||
{% trans "Cancel event" %}
|
{% trans "Cancel event" %}
|
||||||
</a>
|
{% else %}
|
||||||
{% else %}
|
{% trans "No permission" %}
|
||||||
{% trans "No permission" %}
|
{% endif %}
|
||||||
{% endif %}
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,15 +62,16 @@
|
|||||||
<h3 class="panel-title">{% trans "Delete personal data" %}</h3>
|
<h3 class="panel-title">{% trans "Delete personal data" %}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row panel-body">
|
<div class="row panel-body">
|
||||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
<div class="col-sm-12 col-lg-6">
|
||||||
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
You can remove personal data such as names and email addresses from your event and only retain the
|
You can remove personal data such as names and email addresses from your event and only retain the
|
||||||
financial information such as the number and type of tickets sold.
|
financial information such as the number and type of tickets sold.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-3">
|
<div class="col-sm-12 col-lg-6 text-right">
|
||||||
<a href="
|
<a href="{% url "control:event.shredder.start" event=request.event.slug organizer=request.organizer.slug %}" class="btn btn-danger btn-lg">
|
||||||
{% url "control:event.shredder.start" event=request.event.slug organizer=request.organizer.slug %}" class="btn btn-danger btn-lg btn-block">
|
|
||||||
<span class="fa fa-eraser"></span>
|
<span class="fa fa-eraser"></span>
|
||||||
{% trans "Delete personal data" %}
|
{% trans "Delete personal data" %}
|
||||||
</a>
|
</a>
|
||||||
@@ -80,15 +84,17 @@
|
|||||||
<h3 class="panel-title">{% trans "Delete event" %}</h3>
|
<h3 class="panel-title">{% trans "Delete event" %}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row panel-body">
|
<div class="row panel-body">
|
||||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
<div class="col-sm-12 col-lg-6">
|
||||||
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
You can delete your event completely only as long as it does not contain any undeletable data, such as
|
You can delete your event completely only as long as it does not contain any undeletable data, such as
|
||||||
orders not performed in test mode.
|
orders not performed in test mode.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-3">
|
<div class="col-sm-12 col-lg-6 text-right">
|
||||||
<a href="{% url "control:event.delete" organizer=request.organizer.slug event=request.event.slug %}"
|
<a href="{% url "control:event.delete" organizer=request.organizer.slug event=request.event.slug %}"
|
||||||
class="btn btn-danger btn-block btn-lg {% if not request.event.allow_delete %}disabled{% endif %}">
|
class="btn btn-danger btn-lg {% if not request.event.allow_delete %}disabled{% endif %}">
|
||||||
<span class="fa fa-trash"></span>
|
<span class="fa fa-trash"></span>
|
||||||
{% trans "Delete event" %}
|
{% trans "Delete event" %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{% extends "pretixcontrol/event/base.html" %}
|
{% extends "pretixcontrol/event/base.html" %}
|
||||||
|
{% load eventsignal %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% trans "Approve order" %}
|
{% trans "Approve order" %}
|
||||||
@@ -7,6 +8,9 @@
|
|||||||
<h1>
|
<h1>
|
||||||
{% trans "Approve order" %}
|
{% trans "Approve order" %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
{% eventsignal request.event "pretix.control.signals.order_approve_info" order=order request=request %}
|
||||||
|
|
||||||
<p>{% blocktrans trimmed %}
|
<p>{% blocktrans trimmed %}
|
||||||
Do you really want to approve this order?
|
Do you really want to approve this order?
|
||||||
{% endblocktrans %}</p>
|
{% endblocktrans %}</p>
|
||||||
|
|||||||
@@ -134,6 +134,39 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if invoice_qualified and order.invoice_dirty %}
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
This order was changed after the last invoice was generated. A new invoice was not generated yet, because invoices are configured to be generated on payment or if required by the payment method.
|
||||||
|
A new invoice will be generated once the customer pays the invoice or selects a payment method that requires an invoice.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
{% if "event.orders:write" in request.eventpermset %}
|
||||||
|
<p>
|
||||||
|
{% if uncancelled_invoice %}
|
||||||
|
<form action="{% url "control:event.order.reissueinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=uncancelled_invoice.pk %}"
|
||||||
|
method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-default" type="submit">
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
Reissue invoice
|
||||||
|
{% endblocktrans %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% elif can_generate_invoice %}
|
||||||
|
<form method="post" action="{% url "control:event.order.geninvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-default">
|
||||||
|
{% trans "Generate invoice" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-lg-10">
|
<div class="col-xs-12 col-lg-10">
|
||||||
{% for cr in order.cancellation_requests.all %}
|
{% for cr in order.cancellation_requests.all %}
|
||||||
@@ -553,7 +586,7 @@
|
|||||||
<span class="fa fa-print"></span>
|
<span class="fa fa-print"></span>
|
||||||
{{ pl.datetime|date:"SHORT_DATETIME_FORMAT" }}
|
{{ pl.datetime|date:"SHORT_DATETIME_FORMAT" }}
|
||||||
{{ pl.get_type_display }}
|
{{ pl.get_type_display }}
|
||||||
({{ pl.source }}{% if pl.device %}, #{{ pl.device.device_id }}{% endif %})
|
({{ pl.source }}{% if pl.device %}, {{ pl.device.name }} - #{{ pl.device.device_id }}{% endif %})
|
||||||
{% if not pl.successful %}<span class="fa fa-warning fa-fw"></span>{% endif %}
|
{% if not pl.successful %}<span class="fa fa-warning fa-fw"></span>{% endif %}
|
||||||
<br>
|
<br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -1045,7 +1078,7 @@
|
|||||||
<dt>{% trans "VAT ID" %}</dt>
|
<dt>{% trans "VAT ID" %}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{ order.invoice_address.vat_id }}
|
{{ order.invoice_address.vat_id }}
|
||||||
{% if order.invoice_address.vat_id_validated %}
|
{% if order.invoice_address.vat_id and order.invoice_address.vat_id_validated %}
|
||||||
<span class="fa fa-check" data-toggle="tooltip" title="{% blocktrans trimmed %}Valid EU VAT ID{% endblocktrans %}"></span>
|
<span class="fa fa-check" data-toggle="tooltip" title="{% blocktrans trimmed %}Valid EU VAT ID{% endblocktrans %}"></span>
|
||||||
{% elif order.invoice_address.vat_id %}
|
{% elif order.invoice_address.vat_id %}
|
||||||
<form class="form-inline helper-display-inline" method="post"
|
<form class="form-inline helper-display-inline" method="post"
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
<legend>{% trans "How should the refund be sent?" %}</legend>
|
<legend>{% trans "How should the refund be sent?" %}</legend>
|
||||||
<p>
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
Any payments that you selected for automatical refunds will be immediately communicate the refund
|
Any payments you selected for automatic refunds will have the refund request sent immediately to the
|
||||||
request to the respective payment provider. Manual refunds will be created as pending refunds, you
|
respective payment provider. Manual refunds will be created as pending refunds, which you can later
|
||||||
can then later mark them as done once you actually transferred the money back to the customer.
|
mark as done once you have actually transferred the money back to the customer.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form action="{% url "control:organizer.device.bulk_edit" organizer=request.organizer.slug %}" method="post">
|
<form action="#will-be-overridden" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% for field in filter_form %}
|
{% for field in filter_form %}
|
||||||
{{ field.as_hidden }}
|
{{ field.as_hidden }}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@
|
|||||||
<a href="?{% url_replace request 'ordering' 'identifier' %}"><i class="fa fa-caret-up"></i></a>
|
<a href="?{% url_replace request 'ordering' 'identifier' %}"><i class="fa fa-caret-up"></i></a>
|
||||||
</th>
|
</th>
|
||||||
<th>{% trans "Media type" context "reusable_media" %}
|
<th>{% trans "Media type" context "reusable_media" %}
|
||||||
<a href="?{% url_replace request 'ordering' '-email' %}"><i class="fa fa-caret-down"></i></a>
|
<a href="?{% url_replace request 'ordering' '-type' %}"><i class="fa fa-caret-down"></i></a>
|
||||||
<a href="?{% url_replace request 'ordering' 'email' %}"><i class="fa fa-caret-up"></i></a></th>
|
<a href="?{% url_replace request 'ordering' 'type' %}"><i class="fa fa-caret-up"></i></a></th>
|
||||||
<th>{% trans "Connections" context "reusable_media" %}</th>
|
<th>{% trans "Connections" context "reusable_media" %}</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -90,13 +90,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if m.linked_orderposition %}
|
{% for op in m.linked_orderpositions.all %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-ticket fa-fw"></span>
|
<span class="fa fa-ticket fa-fw"></span>
|
||||||
<a href="{% url "control:event.order" event=m.linked_orderposition.order.event.slug organizer=request.organizer.slug code=m.linked_orderposition.order.code %}">
|
<a href="{% url "control:event.order" event=op.order.event.slug organizer=request.organizer.slug code=op.order.code %}">
|
||||||
{{ m.linked_orderposition.order.code }}</a>-{{ m.linked_orderposition.positionid }}
|
{{ op.order.code }}</a>-{{ op.positionid }}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
{% if m.linked_giftcard %}
|
{% if m.linked_giftcard %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-credit-card fa-fw"></span>
|
<span class="fa fa-credit-card fa-fw"></span>
|
||||||
|
|||||||
@@ -26,7 +26,19 @@
|
|||||||
<dt>{% trans "Media type" context "reusable_media" %}</dt>
|
<dt>{% trans "Media type" context "reusable_media" %}</dt>
|
||||||
<dd>{{ medium.get_type_display }}</dd>
|
<dd>{{ medium.get_type_display }}</dd>
|
||||||
<dt>{% trans "Identifier" context "reusable_media" %}</dt>
|
<dt>{% trans "Identifier" context "reusable_media" %}</dt>
|
||||||
<dd><code>{{ medium.identifier }}</code></dd>
|
<dd>
|
||||||
|
<code id="medium_identifier">{{ medium.identifier }}</code>
|
||||||
|
<button type="button" class="btn btn-default btn-xs btn-clipboard js-only" data-clipboard-target="#medium_identifier">
|
||||||
|
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||||
|
<span class="sr-only">{% trans "Copy to clipboard" %}</span>
|
||||||
|
</button>
|
||||||
|
{% if medium.type == "barcode" %}
|
||||||
|
<button type="button" class="btn btn-default btn-xs js-only" data-toggle="qrcode" data-qrcode="{{ medium.identifier }}">
|
||||||
|
<i class="fa fa-qrcode" aria-hidden="true"></i>
|
||||||
|
<span class="sr-only">{% trans "Create QR code" %}</span>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
<dt>{% trans "Status" %}</dt>
|
<dt>{% trans "Status" %}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{% if not medium.active %}
|
{% if not medium.active %}
|
||||||
@@ -41,34 +53,34 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if medium.customer %}
|
{% if medium.customer %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-user fa-fw"></span>
|
<span class="fa fa-user fa-fw"></span>
|
||||||
{% if "organizer.customers:read" in request.orgapermset %}
|
{% if "organizer.customers:read" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=medium.customer.identifier %}">
|
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=medium.customer.identifier %}">
|
||||||
|
{{ medium.customer }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
{{ medium.customer }}
|
{{ medium.customer }}
|
||||||
</a>
|
{% endif %}
|
||||||
{% else %}
|
</span>
|
||||||
{{ medium.customer }}
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if medium.linked_orderposition %}
|
{% for op in medium.linked_orderpositions.all %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-ticket fa-fw"></span>
|
<span class="fa fa-ticket fa-fw"></span>
|
||||||
<a href="{% url "control:event.order" event=medium.linked_orderposition.order.event.slug organizer=request.organizer.slug code=medium.linked_orderposition.order.code %}">
|
<a href="{% url "control:event.order" event=op.order.event.slug organizer=request.organizer.slug code=op.order.code %}">
|
||||||
{{ medium.linked_orderposition.order.code }}</a>-{{ medium.linked_orderposition.positionid }}
|
{{ op.order.code }}</a>-{{ op.positionid }}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
{% if medium.linked_giftcard %}
|
{% if medium.linked_giftcard %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-credit-card fa-fw"></span>
|
<span class="fa fa-credit-card fa-fw"></span>
|
||||||
{% if "organizer.giftcards:read" in request.orgapermset %}
|
{% if "organizer.giftcards:read" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=medium.linked_giftcard.id %}">
|
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=medium.linked_giftcard.id %}">
|
||||||
{{ medium.linked_giftcard.secret }}
|
{{ medium.linked_giftcard.secret }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ medium.linked_giftcard.secret|slice:":3" }}…
|
{{ medium.linked_giftcard.secret|slice:":3" }}…
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
{% if medium.notes %}
|
{% if medium.notes %}
|
||||||
|
|||||||
@@ -4,290 +4,306 @@
|
|||||||
{% load formset_tags %}
|
{% load formset_tags %}
|
||||||
{% load eventsignal %}
|
{% load eventsignal %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% block title %}{% trans "Date" context "subevent" %}{% endblock %}
|
{% load money %}
|
||||||
|
{% load icon %}
|
||||||
|
{% block title %}{% blocktrans trimmed with name=subevent.name context "subevent" %}Date: {{ name }}
|
||||||
|
{% endblocktrans %}{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if not subevent.pk %}
|
<h1>
|
||||||
<h1>{% trans "Create date" context "subevent" %}</h1>
|
{% blocktrans trimmed with name=subevent.name context "subevent" %}Date: {{ name }}{% endblocktrans %}
|
||||||
{% else %}
|
{% if 'event.subevents:write' in request.eventpermset %}
|
||||||
<h1>{% trans "Date" context "subevent" %}</h1>
|
<a href="{% url "control:event.subevent.edit" event=request.event.slug organizer=request.event.organizer.slug subevent=subevent.pk %}"
|
||||||
{% endif %}
|
class="btn btn-default">
|
||||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
<span class="fa fa-edit"></span>
|
||||||
{% csrf_token %}
|
{% trans "Edit" %}
|
||||||
{% bootstrap_form_errors form %}
|
</a>
|
||||||
{% for f in itemvar_forms %}
|
{% endif %}
|
||||||
{% bootstrap_form_errors f %}
|
</h1>
|
||||||
{% endfor %}
|
<div class="row">
|
||||||
<div class="row">
|
<div class="{% if "event.orders:read" in request.eventpermset %}col-md-5{% else %}col-md-10{% endif %} col-xs-12">
|
||||||
<div class="col-xs-12 {% if subevent.pk %}col-lg-10{% endif %}">
|
<fieldset>
|
||||||
<fieldset>
|
<legend>{% trans "General information" %}</legend>
|
||||||
<legend>{% trans "General information" %}</legend>
|
<dl class="dl-horizontal">
|
||||||
{% bootstrap_field form.name layout="control" %}
|
<dt>{% trans "Name" %}</dt>
|
||||||
{% bootstrap_field form.active layout="control" %}
|
<dd>{{ subevent.name }}</dd>
|
||||||
{% bootstrap_field form.date_from layout="control" %}
|
<dt>{% trans "ID" %}</dt>
|
||||||
{% bootstrap_field form.date_to layout="control" %}
|
<dd>#{{ subevent.pk }}</dd>
|
||||||
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
<dt>{% trans "Status" %}</dt>
|
||||||
{% bootstrap_field form.date_admission layout="control" %}
|
<dd>
|
||||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
{% if not subevent.active %}
|
||||||
{% bootstrap_field form.is_public layout="control" %}
|
<span class="label label-danger">{% trans "Disabled" %}</span>
|
||||||
{% bootstrap_field form.comment layout="control" %}
|
{% elif subevent.presale_has_ended %}
|
||||||
{% if meta_forms %}
|
<span class="label label-warning">{% trans "Presale over" %}</span>
|
||||||
<div class="form-group metadata-group">
|
{% elif not subevent.presale_is_running %}
|
||||||
<label class="col-md-3 control-label">{% trans "Meta data" %}</label>
|
<span class="label label-warning">{% trans "Presale not started" %}</span>
|
||||||
<div class="col-md-9">
|
{% else %}
|
||||||
{% for form in meta_forms %}
|
<span class="label label-success">{% trans "On sale" %}</span>
|
||||||
<div class="row">
|
{% endif %}
|
||||||
<div class="col-md-4">
|
</dd>
|
||||||
<label for="{{ form.value.id_for_label }}">
|
<dt>{% trans "Event start time" %}</dt>
|
||||||
{{ form.property.name }}
|
<dd>{{ subevent.date_from|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||||
</label>
|
<dt>{% trans "Event end time" %}</dt>
|
||||||
</div>
|
<dd>{{ subevent.date_to|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||||
<div class="col-md-8">
|
{% if subevent.date_admission %}
|
||||||
{% bootstrap_form form layout="inline" error_types="all" %}
|
<dt>{% trans "Admission time" %}</dt>
|
||||||
</div>
|
<dd>{{ subevent.date_admission|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</fieldset>
|
{% if subevent.presale_start %}
|
||||||
<fieldset>
|
<dt>{% trans "Start of presale" %}</dt>
|
||||||
<legend>{% trans "Timeline" %}</legend>
|
<dd>{{ subevent.presale_start|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||||
{% bootstrap_field form.presale_start layout="control" %}
|
{% endif %}
|
||||||
{% bootstrap_field form.presale_end layout="control" %}
|
{% if subevent.presale_end %}
|
||||||
</fieldset>
|
<dt>{% trans "End of presale" %}</dt>
|
||||||
<fieldset>
|
<dd>{{ subevent.presale_end|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||||
<legend>{% trans "Quotas" %}</legend>
|
{% endif %}
|
||||||
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
{% if subevent.location %}
|
||||||
{{ formset.management_form }}
|
<dt>{% trans "Location" %}</dt>
|
||||||
{% bootstrap_formset_errors formset %}
|
<dd>{{ subevent.location|linebreaksbr }}</dd>
|
||||||
<div data-formset-body>
|
{% endif %}
|
||||||
{% for form in formset %}
|
<dt>{% trans "Show in lists" %}</dt>
|
||||||
<div class="panel panel-default" data-formset-form>
|
<dd>{{ subevent.is_public|yesno }}</dd>
|
||||||
<div class="sr-only">
|
{% for k, v in subevent.meta_data.items %}
|
||||||
{{ form.id }}
|
<dt>{{ k }}</dt>
|
||||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
<dd>{{ v }}</dd>
|
||||||
</div>
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-10">
|
|
||||||
{% bootstrap_field form.name 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>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body form-horizontal">
|
|
||||||
{% bootstrap_form_errors form %}
|
|
||||||
{% bootstrap_field form.size layout="control" %}
|
|
||||||
{% bootstrap_field form.itemvars layout="control" %}
|
|
||||||
{% bootstrap_field form.release_after_exit layout="control" %}
|
|
||||||
{% bootstrap_field form.ignore_for_event_availability layout="control" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<script type="form-template" data-formset-empty-form>
|
|
||||||
{% escapescript %}
|
|
||||||
<div class="panel panel-default" data-formset-form>
|
|
||||||
<div class="sr-only">
|
|
||||||
{{ formset.empty_form.id }}
|
|
||||||
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
|
||||||
</div>
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-10">
|
|
||||||
{% bootstrap_field formset.empty_form.name 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>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body form-horizontal">
|
|
||||||
{% bootstrap_field formset.empty_form.size layout="control" %}
|
|
||||||
{% bootstrap_field formset.empty_form.itemvars layout="control" %}
|
|
||||||
{% bootstrap_field formset.empty_form.release_after_exit layout="control" %}
|
|
||||||
{% bootstrap_field formset.empty_form.ignore_for_event_availability layout="control" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endescapescript %}
|
|
||||||
</script>
|
|
||||||
<p>
|
|
||||||
<button type="button" class="btn btn-default" data-formset-add>
|
|
||||||
<i class="fa fa-plus"></i> {% trans "Add a new quota" %}</button>
|
|
||||||
</p>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{% trans "Product settings" %}</legend>
|
|
||||||
<p class="text-muted">
|
|
||||||
{% trans "These settings are optional, if you leave them empty, the default values from the product settings will be used." %}
|
|
||||||
</p>
|
|
||||||
{% for f in itemvar_forms %}
|
|
||||||
<div data-itemvar="{{ f.item.id }}{% if f.variation %}-{{ f.variation.id }}{% endif %}">
|
|
||||||
{% bootstrap_form_errors f %}
|
|
||||||
<div class="form-group subevent-itemvar-group">
|
|
||||||
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
|
|
||||||
{% if f.variation %}{{ f.item }} – {{ f.variation }}{% else %}{{ f.item }}{% endif %}
|
|
||||||
</label>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
|
|
||||||
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<br>
|
|
||||||
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group subevent-itemvar-group">
|
|
||||||
<div class="col-md-4 col-md-offset-3">
|
|
||||||
<label for="{{ f.available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
|
|
||||||
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
|
|
||||||
{% bootstrap_field f.available_from form_group_class="foo" layout="inline" %}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label for="{{ f.available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
|
|
||||||
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
|
|
||||||
{% bootstrap_field f.available_until form_group_class="" layout="inline" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</fieldset>
|
{% if subevent.comment %}
|
||||||
|
<dt>{% trans "Internal comment" %}</dt>
|
||||||
|
<dd>{{ subevent.comment|linebreaksbr }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Quotas" %}</legend>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-quotas">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Quota name" %}</th>
|
||||||
|
<th>{% trans "Products" %}</th>
|
||||||
|
<th>{% trans "Total capacity" %}</th>
|
||||||
|
<th>{% trans "Capacity left" %}</th>
|
||||||
|
<th class="action-col-2"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for q in quotas %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong><a
|
||||||
|
href="{% url "control:event.items.quotas.show" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}">{{ q.name }}</a></strong>
|
||||||
|
{% if q.ignore_for_event_availability %}
|
||||||
|
<span class="fa fa-eye-slash text-muted" data-toggle="tooltip"
|
||||||
|
title="{% trans "Ignore this quota when determining event availability" %}"></span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
{% for item in q.cached_items %}
|
||||||
|
{% if not item.has_variations %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% for v in q.variations.all %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=v.item.id %}#tab-0-3-open">
|
||||||
|
{{ v.item }} – {{ v }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>{% if q.size == None %}Unlimited{% else %}{{ q.size }}{% endif %}</td>
|
||||||
|
<td>{% include "pretixcontrol/items/fragment_quota_availability.html" with availability=q.cached_avail closed=q.closed %}</td>
|
||||||
|
<td class="text-right flip">
|
||||||
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{% if checkinlists %}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{% trans "Check-in lists" %}</legend>
|
<legend>{% trans "Check-in lists" %}</legend>
|
||||||
<p class="help-block">
|
<div class="table-responsive">
|
||||||
{% blocktrans trimmed %}
|
<table class="table table-hover table-quotas">
|
||||||
You can choose to either add one or more check-in lists for every date in your series individually,
|
<thead>
|
||||||
or use just one check-in list for all your dates and limit admission through check-in rules. Which
|
<tr>
|
||||||
approach is better depends on multiple factors, such as the number of dates in your series. For a
|
<th>{% trans "Name" %}</th>
|
||||||
series with one or less event date per day, individual lists are usually more helpful. If you
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
use dates to represent many time slots on the same day, or even overlapping time slots, working with
|
<th>{% trans "Checked in" %}</th>
|
||||||
just one large check-in list will be easier.
|
{% endif %}
|
||||||
{% endblocktrans %}
|
<th>{% trans "Products" %}</th>
|
||||||
</p>
|
<th class="action-col-2"></th>
|
||||||
<div class="formset" data-formset data-formset-prefix="{{ cl_formset.prefix }}">
|
</tr>
|
||||||
{{ cl_formset.management_form }}
|
</thead>
|
||||||
{% bootstrap_formset_errors cl_formset %}
|
<tbody>
|
||||||
<div data-formset-body>
|
{% for cl in checkinlists %}
|
||||||
{% for form in cl_formset %}
|
<tr>
|
||||||
<div class="panel panel-default" data-formset-form>
|
<td>
|
||||||
<div class="sr-only">
|
<strong><a
|
||||||
{{ form.id }}
|
href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}">{{ cl.name }}</a></strong>
|
||||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
</td>
|
||||||
</div>
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
<div class="panel-heading">
|
<td>
|
||||||
<h4 class="panel-title">
|
<div class="quotabox availability">
|
||||||
<div class="row">
|
<div class="progress">
|
||||||
<div class="col-md-10">
|
<div class="progress-bar progress-bar-success progress-bar-{{ cl.percent }}">
|
||||||
{% bootstrap_field form.name layout='inline' form_group_class="" %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 text-right flip">
|
<div class="numbers">
|
||||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
{{ cl.checkin_count|default_if_none:"0" }} /
|
||||||
<i class="fa fa-trash"></i></button>
|
{{ cl.position_count|default_if_none:"0" }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</td>
|
||||||
</div>
|
{% endif %}
|
||||||
<div class="panel-body form-horizontal">
|
<td>
|
||||||
{% bootstrap_form_errors form %}
|
{% if cl.all_products %}
|
||||||
{% bootstrap_field form.include_pending layout="control" %}
|
<em>{% trans "All" %}</em>
|
||||||
{% bootstrap_field form.all_products layout="control" %}
|
{% else %}
|
||||||
{% bootstrap_field form.limit_products layout="control" %}
|
<ul>
|
||||||
{% bootstrap_field form.allow_entry_after_exit layout="control" %}
|
{% for item in cl.limit_products.all %}
|
||||||
{% if form.gates %}
|
<li>
|
||||||
{% bootstrap_field form.gates layout="control" %}
|
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</td>
|
||||||
</div>
|
<td class="text-right flip">
|
||||||
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-eye"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
{% if "event.settings.general:write" in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.orders.checkinlists.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ cl.id }}"
|
||||||
|
class="btn btn-sm btn-default" title="{% trans "Clone" %}"
|
||||||
|
data-toggle="tooltip">
|
||||||
|
<span class="fa fa-copy"></span>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</tbody>
|
||||||
<script type="form-template" data-formset-empty-form>
|
</table>
|
||||||
{% escapescript %}
|
|
||||||
<div class="panel panel-default" data-formset-form>
|
|
||||||
<div class="sr-only">
|
|
||||||
{{ cl_formset.empty_form.id }}
|
|
||||||
{% bootstrap_field cl_formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
|
||||||
</div>
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-10">
|
|
||||||
{% bootstrap_field cl_formset.empty_form.name 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>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body form-horizontal">
|
|
||||||
{% bootstrap_field cl_formset.empty_form.include_pending layout="control" %}
|
|
||||||
{% bootstrap_field cl_formset.empty_form.all_products layout="control" %}
|
|
||||||
{% bootstrap_field cl_formset.empty_form.limit_products layout="control" %}
|
|
||||||
{% bootstrap_field cl_formset.empty_form.allow_entry_after_exit layout="control" %}
|
|
||||||
{% if cl_formset.empty_form.gates %}
|
|
||||||
{% bootstrap_field cl_formset.empty_form.gates layout="control" %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endescapescript %}
|
|
||||||
</script>
|
|
||||||
<p>
|
|
||||||
<button type="button" class="btn btn-default" data-formset-add>
|
|
||||||
<i class="fa fa-plus"></i> {% trans "Add a new check-in list" %}
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% for f in plugin_forms %}
|
{% endif %}
|
||||||
{% if f.title %}
|
{% eventsignal request.event "pretix.control.signals.subevent_detail_html" subevent=subevent %}
|
||||||
<fieldset>
|
</div>
|
||||||
<legend>{{ f.title }}</legend>
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
{% if f.template %}
|
<div class="col-md-5 col-xs-12">
|
||||||
{% include f.template with form=f %}
|
|
||||||
{% else %}
|
|
||||||
{% bootstrap_form f layout="control" %}
|
|
||||||
{% endif %}
|
|
||||||
</fieldset>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{% trans "Additional settings" %}</legend>
|
<legend>
|
||||||
{% for f in plugin_forms %}
|
{% trans "Orders" %}
|
||||||
{% if not f.title %}
|
<span class="badge">
|
||||||
{% if f.template %}
|
{{ order_count }}
|
||||||
{% include f.template with form=f %}
|
</span>
|
||||||
{% else %}
|
</legend>
|
||||||
{% bootstrap_form f layout="control" %}
|
{% if order_count %}
|
||||||
{% endif %}
|
<div class="table-responsive">
|
||||||
|
<table class="table table-condensed table-hover table-orders">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Order code" %}</th>
|
||||||
|
<th>{% trans "Details" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for o in orders %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=o.code %}">
|
||||||
|
{{ o.code }}
|
||||||
|
</a>
|
||||||
|
</strong>
|
||||||
|
<br>
|
||||||
|
{% if o.testmode %}
|
||||||
|
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if o.status == "p" and o.pcnt == 0 %}
|
||||||
|
{# Everything related to this subevent is canceled #}
|
||||||
|
<span class="label label-danger">
|
||||||
|
<span class="fa fa-times"></span>
|
||||||
|
{% trans "partially canceled" %}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
{% include "pretixcontrol/orders/fragment_order_status.html" with order=o %}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if "." in o.sales_channel.icon %}
|
||||||
|
<img src="{% static o.sales_channel.icon %}" class="fa-like-image"
|
||||||
|
data-toggle="tooltip" title="{{ o.sales_channel.label }}">
|
||||||
|
{% else %}
|
||||||
|
<span class="fa fa-fw fa-{{ o.sales_channel.icon }} text-muted"
|
||||||
|
data-toggle="tooltip" title="{{ o.sales_channel.label }}"></span>
|
||||||
|
{% endif %}
|
||||||
|
{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}
|
||||||
|
{% if o.email %}
|
||||||
|
<br>{% icon "envelope-o fa-fw text-muted" %}
|
||||||
|
{{ o.email|default_if_none:"" }}
|
||||||
|
{% endif %}
|
||||||
|
{% if o.invoice_address.name %}
|
||||||
|
<br>{% icon "user fa-fw text-muted" %} {{ o.invoice_address.name }}
|
||||||
|
{% endif %}
|
||||||
|
<br>{% icon "ticket text-muted fa-fw" %} {{ o.pcnt }}
|
||||||
|
{% if o.comment %}
|
||||||
|
<br>
|
||||||
|
<span class="text-muted">
|
||||||
|
{{ o.comment|linebreaksbr }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if o.custom_followup_due %}
|
||||||
|
<br>
|
||||||
|
<span class="label label-danger">{% blocktrans trimmed with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}
|
||||||
|
TODO {{ date }}{% endblocktrans %}</span>
|
||||||
|
{% elif o.custom_followup_at %}
|
||||||
|
<br>
|
||||||
|
<span class="label label-default">{% blocktrans trimmed with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}
|
||||||
|
TODO {{ date }}{% endblocktrans %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% if order_count > 10 %}
|
||||||
|
<p class="text-center">
|
||||||
|
<a href="{% url "control:event.orders" organizer=request.organizer.slug event=request.event.slug %}?subevent={{ subevent.pk }}"
|
||||||
|
class="btn btn-default">
|
||||||
|
{% trans "View all" %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% else %}
|
||||||
|
<div class="empty-collection">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
No orders found.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
{% if subevent.pk %}
|
{% endif %}
|
||||||
<div class="col-xs-12 col-lg-2">
|
<div class="col-md-2 col-xs-12">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">
|
<h3 class="panel-title">
|
||||||
{% trans "Date history" context "subevent" %}
|
{% trans "Date history" context "subevent" %}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
|
||||||
{% include "pretixcontrol/includes/logs.html" with obj=subevent %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% include "pretixcontrol/includes/logs.html" with obj=subevent %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group submit-group submit-group-sticky">
|
</div>
|
||||||
<button type="submit" class="btn btn-primary btn-save">
|
|
||||||
{% trans "Save" %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,296 @@
|
|||||||
|
{% extends "pretixcontrol/event/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load formset_tags %}
|
||||||
|
{% load eventsignal %}
|
||||||
|
{% load static %}
|
||||||
|
{% block title %}{% trans "Date" context "subevent" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% if not subevent.pk %}
|
||||||
|
<h1>{% trans "Create date" context "subevent" %}</h1>
|
||||||
|
{% else %}
|
||||||
|
<h1>{% trans "Date" context "subevent" %}</h1>
|
||||||
|
{% endif %}
|
||||||
|
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_form_errors form %}
|
||||||
|
{% for f in itemvar_forms %}
|
||||||
|
{% bootstrap_form_errors f %}
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 {% if subevent.pk %}col-lg-10{% endif %}">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "General information" %}</legend>
|
||||||
|
{% bootstrap_field form.name layout="control" %}
|
||||||
|
{% bootstrap_field form.active layout="control" %}
|
||||||
|
{% bootstrap_field form.date_from layout="control" %}
|
||||||
|
{% bootstrap_field form.date_to layout="control" %}
|
||||||
|
{% include "pretixcontrol/event/fragment_geodata.html" %}
|
||||||
|
{% bootstrap_field form.date_admission layout="control" %}
|
||||||
|
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||||
|
{% bootstrap_field form.is_public layout="control" %}
|
||||||
|
{% bootstrap_field form.comment layout="control" %}
|
||||||
|
{% if meta_forms %}
|
||||||
|
<div class="form-group metadata-group">
|
||||||
|
<label class="col-md-3 control-label">{% trans "Meta data" %}</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
{% for form in meta_forms %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="{{ form.value.id_for_label }}">
|
||||||
|
{{ form.property.name }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{% bootstrap_form form layout="inline" error_types="all" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Timeline" %}</legend>
|
||||||
|
{% bootstrap_field form.presale_start layout="control" %}
|
||||||
|
{% bootstrap_field form.presale_end layout="control" %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Quotas" %}</legend>
|
||||||
|
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
||||||
|
{{ formset.management_form }}
|
||||||
|
{% bootstrap_formset_errors formset %}
|
||||||
|
<div data-formset-body>
|
||||||
|
{% for form in formset %}
|
||||||
|
<div class="panel panel-default" data-formset-form>
|
||||||
|
<div class="sr-only">
|
||||||
|
{{ form.id }}
|
||||||
|
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
{% bootstrap_field form.name 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>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body form-horizontal">
|
||||||
|
{% bootstrap_form_errors form %}
|
||||||
|
{% bootstrap_field form.size layout="control" %}
|
||||||
|
{% bootstrap_field form.itemvars layout="control" %}
|
||||||
|
{% bootstrap_field form.release_after_exit layout="control" %}
|
||||||
|
{% bootstrap_field form.ignore_for_event_availability layout="control" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<script type="form-template" data-formset-empty-form>
|
||||||
|
{% escapescript %}
|
||||||
|
<div class="panel panel-default" data-formset-form>
|
||||||
|
<div class="sr-only">
|
||||||
|
{{ formset.empty_form.id }}
|
||||||
|
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
{% bootstrap_field formset.empty_form.name 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>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body form-horizontal">
|
||||||
|
{% bootstrap_field formset.empty_form.size layout="control" %}
|
||||||
|
{% bootstrap_field formset.empty_form.itemvars layout="control" %}
|
||||||
|
{% bootstrap_field formset.empty_form.release_after_exit layout="control" %}
|
||||||
|
{% bootstrap_field formset.empty_form.ignore_for_event_availability layout="control" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endescapescript %}
|
||||||
|
</script>
|
||||||
|
<p>
|
||||||
|
<button type="button" class="btn btn-default" data-formset-add>
|
||||||
|
<i class="fa fa-plus"></i> {% trans "Add a new quota" %}</button>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Product settings" %}</legend>
|
||||||
|
<p class="text-muted">
|
||||||
|
{% trans "These settings are optional, if you leave them empty, the default values from the product settings will be used." %}
|
||||||
|
</p>
|
||||||
|
{% for f in itemvar_forms %}
|
||||||
|
<div data-itemvar="{{ f.item.id }}{% if f.variation %}-{{ f.variation.id }}{% endif %}">
|
||||||
|
{% bootstrap_form_errors f %}
|
||||||
|
<div class="form-group subevent-itemvar-group">
|
||||||
|
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
|
||||||
|
{% if f.variation %}{{ f.item }} – {{ f.variation }}{% else %}{{ f.item }}{% endif %}
|
||||||
|
</label>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
|
||||||
|
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<br>
|
||||||
|
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group subevent-itemvar-group">
|
||||||
|
<div class="col-md-4 col-md-offset-3">
|
||||||
|
<label for="{{ f.available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
|
||||||
|
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
|
||||||
|
{% bootstrap_field f.available_from form_group_class="foo" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="{{ f.available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
|
||||||
|
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
|
||||||
|
{% bootstrap_field f.available_until form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Check-in lists" %}</legend>
|
||||||
|
<p class="help-block">
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
You can choose to either add one or more check-in lists for every date in your series individually,
|
||||||
|
or use just one check-in list for all your dates and limit admission through check-in rules. Which
|
||||||
|
approach is better depends on multiple factors, such as the number of dates in your series. For a
|
||||||
|
series with one or less event date per day, individual lists are usually more helpful. If you
|
||||||
|
use dates to represent many time slots on the same day, or even overlapping time slots, working with
|
||||||
|
just one large check-in list will be easier.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
<div class="formset" data-formset data-formset-prefix="{{ cl_formset.prefix }}">
|
||||||
|
{{ cl_formset.management_form }}
|
||||||
|
{% bootstrap_formset_errors cl_formset %}
|
||||||
|
<div data-formset-body>
|
||||||
|
{% for form in cl_formset %}
|
||||||
|
<div class="panel panel-default" data-formset-form>
|
||||||
|
<div class="sr-only">
|
||||||
|
{{ form.id }}
|
||||||
|
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
{% bootstrap_field form.name 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>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body form-horizontal">
|
||||||
|
{% bootstrap_form_errors form %}
|
||||||
|
{% bootstrap_field form.include_pending layout="control" %}
|
||||||
|
{% bootstrap_field form.all_products layout="control" %}
|
||||||
|
{% bootstrap_field form.limit_products layout="control" %}
|
||||||
|
{% bootstrap_field form.allow_entry_after_exit layout="control" %}
|
||||||
|
{% if form.gates %}
|
||||||
|
{% bootstrap_field form.gates layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<script type="form-template" data-formset-empty-form>
|
||||||
|
{% escapescript %}
|
||||||
|
<div class="panel panel-default" data-formset-form>
|
||||||
|
<div class="sr-only">
|
||||||
|
{{ cl_formset.empty_form.id }}
|
||||||
|
{% bootstrap_field cl_formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||||
|
</div>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
{% bootstrap_field cl_formset.empty_form.name 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>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body form-horizontal">
|
||||||
|
{% bootstrap_field cl_formset.empty_form.include_pending layout="control" %}
|
||||||
|
{% bootstrap_field cl_formset.empty_form.all_products layout="control" %}
|
||||||
|
{% bootstrap_field cl_formset.empty_form.limit_products layout="control" %}
|
||||||
|
{% bootstrap_field cl_formset.empty_form.allow_entry_after_exit layout="control" %}
|
||||||
|
{% if cl_formset.empty_form.gates %}
|
||||||
|
{% bootstrap_field cl_formset.empty_form.gates layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endescapescript %}
|
||||||
|
</script>
|
||||||
|
<p>
|
||||||
|
<button type="button" class="btn btn-default" data-formset-add>
|
||||||
|
<i class="fa fa-plus"></i> {% trans "Add a new check-in list" %}
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
{% for f in plugin_forms %}
|
||||||
|
{% if f.title %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{ f.title }}</legend>
|
||||||
|
{% if f.template %}
|
||||||
|
{% include f.template with form=f %}
|
||||||
|
{% else %}
|
||||||
|
{% bootstrap_form f layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
</fieldset>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Additional settings" %}</legend>
|
||||||
|
{% for f in plugin_forms %}
|
||||||
|
{% if not f.title %}
|
||||||
|
{% if f.template %}
|
||||||
|
{% include f.template with form=f %}
|
||||||
|
{% else %}
|
||||||
|
{% bootstrap_form f layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{% if subevent.pk %}
|
||||||
|
<div class="col-xs-12 col-lg-2">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">
|
||||||
|
{% trans "Date history" context "subevent" %}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
{% include "pretixcontrol/includes/logs.html" with obj=subevent %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group submit-group submit-group-sticky">
|
||||||
|
<a href="{{ next_url }}" class="btn btn-default btn-cancel">
|
||||||
|
{% trans "Cancel" %}
|
||||||
|
</a>
|
||||||
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
|
{% trans "Save" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>
|
<td>
|
||||||
<strong><a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}">
|
<strong><a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}">
|
||||||
{{ s.name }}</a></strong><br>
|
{{ s.name }}</a></strong><br>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
#{{ s.pk }}
|
#{{ s.pk }}
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if "event.subevents:write" in request.eventpermset %}
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
<a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<a href="{% url "control:event.subevent.edit" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
<div class="btn-group {% if forloop.revcounter0 < 2 %}dropup{% endif %}">
|
<div class="btn-group {% if forloop.revcounter0 < 2 %}dropup{% endif %}">
|
||||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle"
|
<button type="button" class="btn btn-default btn-sm dropdown-toggle"
|
||||||
data-toggle="dropdown">
|
data-toggle="dropdown">
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<a href="{% url "control:event.subevent.delete" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.subevent.delete" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -308,7 +308,8 @@ urlpatterns = [
|
|||||||
re_path(r'^pdf/editor/(?P<filename>[^/]+).pdf$', pdf.PdfView.as_view(), name='pdf.background'),
|
re_path(r'^pdf/editor/(?P<filename>[^/]+).pdf$', pdf.PdfView.as_view(), name='pdf.background'),
|
||||||
re_path(r'^subevents/$', subevents.SubEventList.as_view(), name='event.subevents'),
|
re_path(r'^subevents/$', subevents.SubEventList.as_view(), name='event.subevents'),
|
||||||
re_path(r'^subevents/select2$', typeahead.subevent_select2, name='event.subevents.select2'),
|
re_path(r'^subevents/select2$', typeahead.subevent_select2, name='event.subevents.select2'),
|
||||||
re_path(r'^subevents/(?P<subevent>\d+)/$', subevents.SubEventUpdate.as_view(), name='event.subevent'),
|
re_path(r'^subevents/(?P<subevent>\d+)/$', subevents.SubEventDetail.as_view(), name='event.subevent'),
|
||||||
|
re_path(r'^subevents/(?P<subevent>\d+)/edit$', subevents.SubEventUpdate.as_view(), name='event.subevent.edit'),
|
||||||
re_path(r'^subevents/(?P<subevent>\d+)/delete$', subevents.SubEventDelete.as_view(),
|
re_path(r'^subevents/(?P<subevent>\d+)/delete$', subevents.SubEventDelete.as_view(),
|
||||||
name='event.subevent.delete'),
|
name='event.subevent.delete'),
|
||||||
re_path(r'^subevents/add$', subevents.SubEventCreate.as_view(), name='event.subevents.add'),
|
re_path(r'^subevents/add$', subevents.SubEventCreate.as_view(), name='event.subevents.add'),
|
||||||
|
|||||||
@@ -401,13 +401,14 @@ class CheckinListUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
{
|
{
|
||||||
'id': i.pk,
|
'id': i.pk,
|
||||||
'name': str(i),
|
'name': str(i),
|
||||||
|
'active': i.active,
|
||||||
'variations': [
|
'variations': [
|
||||||
{
|
{
|
||||||
'id': v.pk,
|
'id': v.pk,
|
||||||
'name': str(v.value)
|
'name': str(v.value)
|
||||||
} for v in i.variations.all()
|
} for v in i.variations.all()
|
||||||
]
|
]
|
||||||
} for i in self.request.event.items.filter(active=True).prefetch_related('variations')
|
} for i in self.request.event.items.prefetch_related('variations')
|
||||||
],
|
],
|
||||||
**super().get_context_data(),
|
**super().get_context_data(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ from pretix.control.permissions import (
|
|||||||
from pretix.helpers.models import modelcopy
|
from pretix.helpers.models import modelcopy
|
||||||
|
|
||||||
from ...helpers.compat import CompatDeleteView
|
from ...helpers.compat import CompatDeleteView
|
||||||
from . import CreateView, PaginationMixin, UpdateView
|
from . import CreateView, UpdateView
|
||||||
|
|
||||||
|
|
||||||
class DiscountDelete(EventPermissionRequiredMixin, CompatDeleteView):
|
class DiscountDelete(EventPermissionRequiredMixin, CompatDeleteView):
|
||||||
@@ -183,7 +183,7 @@ class DiscountCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
class DiscountList(PaginationMixin, ListView):
|
class DiscountList(ListView):
|
||||||
model = Discount
|
model = Discount
|
||||||
context_object_name = 'discounts'
|
context_object_name = 'discounts'
|
||||||
template_name = 'pretixcontrol/items/discounts.html'
|
template_name = 'pretixcontrol/items/discounts.html'
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ class CategoryCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
class CategoryList(PaginationMixin, ListView):
|
class CategoryList(ListView):
|
||||||
model = ItemCategory
|
model = ItemCategory
|
||||||
context_object_name = 'categories'
|
context_object_name = 'categories'
|
||||||
template_name = 'pretixcontrol/items/categories.html'
|
template_name = 'pretixcontrol/items/categories.html'
|
||||||
|
|||||||
@@ -554,6 +554,9 @@ class OrderDetail(OrderView):
|
|||||||
ctx['download_buttons'] = self.download_buttons
|
ctx['download_buttons'] = self.download_buttons
|
||||||
ctx['payment_refund_sum'] = self.order.payment_refund_sum
|
ctx['payment_refund_sum'] = self.order.payment_refund_sum
|
||||||
ctx['pending_sum'] = self.order.pending_sum
|
ctx['pending_sum'] = self.order.pending_sum
|
||||||
|
ctx['uncancelled_invoice'] = self.order.invoices.exclude(
|
||||||
|
Exists(self.order.invoices.filter(refers=OuterRef('pk'), is_cancellation=True))
|
||||||
|
).exclude(is_cancellation=True).first()
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|||||||
@@ -3384,8 +3384,10 @@ class ReusableMediaListView(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = self.request.organizer.reusable_media.select_related(
|
qs = self.request.organizer.reusable_media.select_related(
|
||||||
'customer', 'linked_orderposition', 'linked_orderposition__order', 'linked_orderposition__order__event',
|
'customer',
|
||||||
'linked_giftcard'
|
'linked_giftcard',
|
||||||
|
).prefetch_related(
|
||||||
|
Prefetch('linked_orderpositions', queryset=OrderPosition.objects.select_related("order", "order__event"))
|
||||||
)
|
)
|
||||||
if self.filter_form.is_valid():
|
if self.filter_form.is_valid():
|
||||||
qs = self.filter_form.filter_qs(qs)
|
qs = self.filter_form.filter_qs(qs)
|
||||||
@@ -3433,10 +3435,14 @@ class ReusableMediumCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequ
|
|||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
r = super().form_valid(form)
|
r = super().form_valid(form)
|
||||||
form.instance.log_action('pretix.reusable_medium.created', user=self.request.user, data={
|
|
||||||
|
data = {
|
||||||
k: getattr(form.instance, k)
|
k: getattr(form.instance, k)
|
||||||
for k in form.changed_data
|
for k in form.changed_data
|
||||||
})
|
}
|
||||||
|
if "linked_orderpositions" in data:
|
||||||
|
data["linked_orderpositions"] = data["linked_orderpositions"].values_list("pk", flat=True)
|
||||||
|
form.instance.log_action('pretix.reusable_medium.created', user=self.request.user, data=data)
|
||||||
messages.success(self.request, _('Your changes have been saved.'))
|
messages.success(self.request, _('Your changes have been saved.'))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@@ -3461,13 +3467,40 @@ class ReusableMediumUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequ
|
|||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
prev_linked_ops_pks = list(getattr(self.object, "linked_orderpositions").values_list("pk", flat=True))
|
||||||
|
result = super().form_valid(form)
|
||||||
if form.has_changed():
|
if form.has_changed():
|
||||||
self.object.log_action('pretix.reusable_medium.changed', user=self.request.user, data={
|
data = {
|
||||||
k: getattr(self.object, k)
|
k: getattr(self.object, k)
|
||||||
for k in form.changed_data
|
for k in form.changed_data
|
||||||
})
|
}
|
||||||
|
if "linked_orderpositions" in data:
|
||||||
|
# handle changes to linked_orderpositions separately
|
||||||
|
linked_ops_pks = data["linked_orderpositions"].values_list("pk", flat=True)
|
||||||
|
del data["linked_orderpositions"]
|
||||||
|
for op_pk in prev_linked_ops_pks:
|
||||||
|
if op_pk not in linked_ops_pks:
|
||||||
|
self.object.log_action(
|
||||||
|
'pretix.reusable_medium.linked_orderposition.removed',
|
||||||
|
user=self.request.user,
|
||||||
|
data={
|
||||||
|
'linked_orderposition': op_pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
for op_pk in linked_ops_pks:
|
||||||
|
if op_pk not in prev_linked_ops_pks:
|
||||||
|
self.object.log_action(
|
||||||
|
'pretix.reusable_medium.linked_orderposition.added',
|
||||||
|
user=self.request.user,
|
||||||
|
data={
|
||||||
|
'linked_orderposition': op_pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if data:
|
||||||
|
# log change-action only for changes other than linked_orderpositions
|
||||||
|
self.object.log_action('pretix.reusable_medium.changed', user=self.request.user, data=data)
|
||||||
messages.success(self.request, _('Your changes have been saved.'))
|
messages.success(self.request, _('Your changes have been saved.'))
|
||||||
return super().form_valid(form)
|
return result
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('control:organizer.reusable_medium', kwargs={
|
return reverse('control:organizer.reusable_medium', kwargs={
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ from django.contrib import messages
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Count, F, Prefetch, ProtectedError
|
from django.db.models import (
|
||||||
|
Count, Exists, F, OuterRef, Prefetch, ProtectedError, Subquery,
|
||||||
|
)
|
||||||
from django.db.models.functions import Coalesce, TruncDate, TruncTime
|
from django.db.models.functions import Coalesce, TruncDate, TruncTime
|
||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
@@ -49,17 +51,21 @@ from django.shortcuts import redirect, render
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.formats import get_format
|
from django.utils.formats import get_format
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
from django.utils.http import url_has_allowed_host_and_scheme
|
||||||
from django.utils.timezone import make_aware, now
|
from django.utils.timezone import make_aware, now
|
||||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic import CreateView, FormView, ListView, UpdateView
|
from django.views.generic import (
|
||||||
|
CreateView, DetailView, FormView, ListView, UpdateView,
|
||||||
|
)
|
||||||
|
|
||||||
from pretix.base.models import CartPosition, LogEntry
|
from pretix.base.models import CartPosition, LogEntry, OrderPosition
|
||||||
from pretix.base.models.checkin import CheckinList
|
from pretix.base.models.checkin import CheckinList
|
||||||
from pretix.base.models.event import SubEvent, SubEventMetaValue
|
from pretix.base.models.event import SubEvent, SubEventMetaValue
|
||||||
from pretix.base.models.items import (
|
from pretix.base.models.items import (
|
||||||
ItemVariation, Quota, SubEventItem, SubEventItemVariation,
|
Item, ItemVariation, Quota, SubEventItem, SubEventItemVariation,
|
||||||
)
|
)
|
||||||
|
from pretix.base.models.orders import CancellationRequest
|
||||||
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
|
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
|
||||||
from pretix.base.services import tickets
|
from pretix.base.services import tickets
|
||||||
from pretix.base.services.quotas import QuotaAvailability
|
from pretix.base.services.quotas import QuotaAvailability
|
||||||
@@ -505,9 +511,68 @@ class SubEventEditorMixin(MetaDataEditorMixin):
|
|||||||
) and self.cl_formset.is_valid() and all(f.is_valid() for f in self.plugin_forms)
|
) and self.cl_formset.is_valid() and all(f.is_valid() for f in self.plugin_forms)
|
||||||
|
|
||||||
|
|
||||||
class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateView):
|
class SubEventDetail(EventPermissionRequiredMixin, DetailView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/detail.html'
|
template_name = 'pretixcontrol/subevents/detail.html'
|
||||||
|
permission = None
|
||||||
|
context_object_name = 'subevent'
|
||||||
|
|
||||||
|
def get_object(self, queryset=None) -> SubEvent:
|
||||||
|
try:
|
||||||
|
return self.request.event.subevents.get(
|
||||||
|
id=self.kwargs['subevent']
|
||||||
|
)
|
||||||
|
except SubEvent.DoesNotExist:
|
||||||
|
raise Http404(pgettext_lazy("subevent", "The requested date does not exist."))
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
oqs = self.request.event.orders.filter(
|
||||||
|
Exists(
|
||||||
|
OrderPosition.objects.filter(
|
||||||
|
subevent=self.object,
|
||||||
|
order_id=OuterRef("id"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).annotate(
|
||||||
|
pcnt=Subquery(
|
||||||
|
OrderPosition.objects.filter(
|
||||||
|
subevent=self.object,
|
||||||
|
).values("subevent").annotate(c=Count("*")).values("c")
|
||||||
|
),
|
||||||
|
has_cancellation_request=Exists(CancellationRequest.objects.filter(order=OuterRef("pk"))),
|
||||||
|
).select_related("invoice_address").prefetch_related("sales_channel")
|
||||||
|
ctx = {
|
||||||
|
"quotas": self.object.quotas.prefetch_related(
|
||||||
|
Prefetch(
|
||||||
|
"items",
|
||||||
|
queryset=Item.objects.annotate(
|
||||||
|
has_variations=Exists(ItemVariation.objects.filter(item=OuterRef("pk")))
|
||||||
|
),
|
||||||
|
to_attr="cached_items"
|
||||||
|
),
|
||||||
|
"variations",
|
||||||
|
"variations__item",
|
||||||
|
).order_by("name", "pk"),
|
||||||
|
"checkinlists": self.object.checkinlist_set.prefetch_related("limit_products"),
|
||||||
|
"orders": oqs[:11],
|
||||||
|
"order_count": oqs.count(),
|
||||||
|
}
|
||||||
|
|
||||||
|
qa = QuotaAvailability()
|
||||||
|
qa.queue(*ctx["quotas"])
|
||||||
|
qa.compute()
|
||||||
|
for quota in ctx["quotas"]:
|
||||||
|
quota.cached_avail = qa.results[quota]
|
||||||
|
|
||||||
|
return super().get_context_data(
|
||||||
|
**kwargs,
|
||||||
|
**ctx,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateView):
|
||||||
|
model = SubEvent
|
||||||
|
template_name = 'pretixcontrol/subevents/edit.html'
|
||||||
permission = 'event.subevents:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
form_class = SubEventForm
|
form_class = SubEventForm
|
||||||
@@ -531,6 +596,7 @@ class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateVi
|
|||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
self.object = form.save()
|
||||||
self.save_formset(self.object)
|
self.save_formset(self.object)
|
||||||
self.save_cl_formset(self.object)
|
self.save_cl_formset(self.object)
|
||||||
self.save_meta()
|
self.save_meta()
|
||||||
@@ -569,23 +635,31 @@ class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateVi
|
|||||||
f.subevent = self.object
|
f.subevent = self.object
|
||||||
f.save()
|
f.save()
|
||||||
tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk})
|
tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk})
|
||||||
return super().form_valid(form)
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
def get_success_url(self) -> str:
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.subevents', kwargs={
|
if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None):
|
||||||
|
return self.request.GET.get("next")
|
||||||
|
return reverse('control:event.subevent', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
}) + ('?' + self.request.GET.get('returnto') if 'returnto' in self.request.GET else '')
|
'subevent': self.object.pk,
|
||||||
|
})
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs['event'] = self.request.event
|
kwargs['event'] = self.request.event
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
return super().get_context_data(
|
||||||
|
next_url=self.get_success_url()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateView):
|
class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/detail.html'
|
template_name = 'pretixcontrol/subevents/edit.html'
|
||||||
permission = 'event.subevents:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
form_class = SubEventForm
|
form_class = SubEventForm
|
||||||
|
|||||||
@@ -145,11 +145,21 @@ def event_list(request):
|
|||||||
if 'can_copy' in request.GET:
|
if 'can_copy' in request.GET:
|
||||||
qs = EventWizardCopyForm.copy_from_queryset(request.user, request.session)
|
qs = EventWizardCopyForm.copy_from_queryset(request.user, request.session)
|
||||||
else:
|
else:
|
||||||
qs = request.user.get_events_with_any_permission(request)
|
permission = request.GET.get('permission')
|
||||||
|
if permission:
|
||||||
|
qs = request.user.get_events_with_permission(permission, request)
|
||||||
|
else:
|
||||||
|
qs = request.user.get_events_with_any_permission(request)
|
||||||
|
|
||||||
|
name_slug_q = Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query)
|
||||||
|
organizer = request.GET.get('organizer')
|
||||||
|
if organizer:
|
||||||
|
qs = qs.filter(organizer__slug=organizer)
|
||||||
|
else:
|
||||||
|
name_slug_q |= Q(organizer__name__icontains=i18ncomp(query)) | Q(organizer__slug__icontains=query)
|
||||||
|
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query) |
|
name_slug_q
|
||||||
Q(organizer__name__icontains=i18ncomp(query)) | Q(organizer__slug__icontains=query)
|
|
||||||
).annotate(
|
).annotate(
|
||||||
min_from=Min('subevents__date_from'),
|
min_from=Min('subevents__date_from'),
|
||||||
max_from=Max('subevents__date_from'),
|
max_from=Max('subevents__date_from'),
|
||||||
@@ -162,10 +172,19 @@ def event_list(request):
|
|||||||
total = qs.count()
|
total = qs.count()
|
||||||
pagesize = 20
|
pagesize = 20
|
||||||
offset = (page - 1) * pagesize
|
offset = (page - 1) * pagesize
|
||||||
|
results = []
|
||||||
|
if page == 1 and 'include_none' in request.GET and not query:
|
||||||
|
results.append({
|
||||||
|
'id': "_none",
|
||||||
|
'text': _("No event"),
|
||||||
|
'name': _("No event"),
|
||||||
|
'type': "event",
|
||||||
|
})
|
||||||
|
results += [
|
||||||
|
serialize_event(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
||||||
|
]
|
||||||
doc = {
|
doc = {
|
||||||
'results': [
|
'results': results,
|
||||||
serialize_event(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
|
||||||
],
|
|
||||||
'pagination': {
|
'pagination': {
|
||||||
"more": total >= (offset + pagesize)
|
"more": total >= (offset + pagesize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is part of pretix (Community Edition).
|
|
||||||
#
|
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
|
||||||
# Copyright (C) 2020-today pretix 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 os
|
|
||||||
import re
|
|
||||||
import shlex
|
|
||||||
|
|
||||||
from compressor.exceptions import FilterError
|
|
||||||
from compressor.filters import CompilerFilter
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class VueCompiler(CompilerFilter):
|
|
||||||
# Based on work (c) Laura Klünder in https://github.com/codingcatgirl/django-vue-rollup
|
|
||||||
# Released under Apache License 2.0
|
|
||||||
|
|
||||||
def __init__(self, content, attrs, **kwargs):
|
|
||||||
config_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'static', 'npm_dir')
|
|
||||||
node_path = os.path.join(settings.STATIC_ROOT, 'node_prefix', 'node_modules')
|
|
||||||
self.rollup_bin = os.path.join(node_path, 'rollup', 'dist', 'bin', 'rollup')
|
|
||||||
rollup_config = os.path.join(config_dir, 'rollup.config.js')
|
|
||||||
if not os.path.exists(self.rollup_bin) and not settings.DEBUG:
|
|
||||||
raise FilterError("Rollup not installed or pretix not built properly, please run 'make npminstall' in source root.")
|
|
||||||
command = (
|
|
||||||
' '.join((
|
|
||||||
'NODE_PATH=' + shlex.quote(node_path),
|
|
||||||
shlex.quote(self.rollup_bin),
|
|
||||||
'-c',
|
|
||||||
shlex.quote(rollup_config))
|
|
||||||
) +
|
|
||||||
' --input {infile} -n {export_name} --file {outfile}'
|
|
||||||
)
|
|
||||||
super().__init__(content, command=command, **kwargs)
|
|
||||||
|
|
||||||
def input(self, **kwargs):
|
|
||||||
if self.filename is None:
|
|
||||||
raise FilterError('VueCompiler can only compile files, not inline code.')
|
|
||||||
if not os.path.exists(self.rollup_bin):
|
|
||||||
raise FilterError("Rollup not installed, please run 'make npminstall' in source root.")
|
|
||||||
self.options += (('export_name', re.sub(
|
|
||||||
r'^([a-z])|[^a-z0-9A-Z]+([a-zA-Z0-9])?',
|
|
||||||
lambda s: s.group(0)[-1].upper(),
|
|
||||||
os.path.basename(self.filename).split('.')[0]
|
|
||||||
)),)
|
|
||||||
return super().input(**kwargs)
|
|
||||||
@@ -40,6 +40,8 @@ from urllib3.util.connection import (
|
|||||||
)
|
)
|
||||||
from urllib3.util.timeout import _DEFAULT_TIMEOUT
|
from urllib3.util.timeout import _DEFAULT_TIMEOUT
|
||||||
|
|
||||||
|
_cgnat_net = ipaddress.ip_network('100.64.0.0/10')
|
||||||
|
|
||||||
|
|
||||||
def monkeypatch_vobject_performance():
|
def monkeypatch_vobject_performance():
|
||||||
"""
|
"""
|
||||||
@@ -152,6 +154,8 @@ def monkeypatch_urllib3_ssrf_protection():
|
|||||||
raise HTTPError(f"Request to local address {sa[0]} blocked")
|
raise HTTPError(f"Request to local address {sa[0]} blocked")
|
||||||
if ip_addr.is_private:
|
if ip_addr.is_private:
|
||||||
raise HTTPError(f"Request to private address {sa[0]} blocked")
|
raise HTTPError(f"Request to private address {sa[0]} blocked")
|
||||||
|
if ip_addr in _cgnat_net:
|
||||||
|
raise HTTPError(f"Request to RFC 6598 address {sa[0]} blocked")
|
||||||
|
|
||||||
sock = None
|
sock = None
|
||||||
try:
|
try:
|
||||||
|
|||||||
+1507
-1421
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -130,7 +130,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -184,172 +183,6 @@ msgstr ""
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -376,46 +209,46 @@ msgid ""
|
|||||||
"browser and try again."
|
"browser and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
"page and try again."
|
"page and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -427,146 +260,6 @@ msgstr ""
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -701,6 +394,16 @@ msgstr ""
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
|
|||||||
+1611
-1522
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: 2021-09-15 11:22+0000\n"
|
"PO-Revision-Date: 2021-09-15 11:22+0000\n"
|
||||||
"Last-Translator: Mohamed Tawfiq <mtawfiq@wafyapp.com>\n"
|
"Last-Translator: Mohamed Tawfiq <mtawfiq@wafyapp.com>\n"
|
||||||
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||||
@@ -134,7 +134,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr "المتابعة"
|
msgstr "المتابعة"
|
||||||
@@ -188,180 +187,6 @@ msgstr "المجموع"
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr "جاري الاتصال بالبنك الذي تتعامل معه …"
|
msgstr "جاري الاتصال بالبنك الذي تتعامل معه …"
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr "اختر قائمة الدخول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr "لم يتم العثور على قوائم دخول نشطة."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr "تبديل قائمة الدخول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr "البحث في النتائج"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr "لم يتم العثور على تذاكر"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr "النتيجة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr "تحتاج هذه التذكرة إلى إهتمام خاص"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr "تغيير المسار"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr "دخول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr "خروج"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr "قم بمسح التذكرة أو إبحث واضغط زر العودة…"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr "تحميل المزيد"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr "ساري المفعول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr "غير مدفوع"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr "ملغاة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr "مستخدم"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "قم بالإلغاء"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr "لم يتم دفع قيمة التذكرة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr "لم يتم دفع قيمة التذكرة بعد، هل تريد المتابعة على أي حال؟"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr "مطلوب معلومات إضافية"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr "تذكرة سارية المفعول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr "تم تسجيل الخروج"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr "تم استخدام التذكرة مسبقا"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr "معلومات مطلوبة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Unknown error."
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr "خطأ غير معروف."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Entry not allowed"
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr "إدخال غير مسموح"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr "إدخال غير مسموح"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr "تم إلغاء رمز التذكرة أو تبديله"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Ticket not paid"
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr "لم يتم دفع قيمة التذكرة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Ticket not paid"
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr "لم يتم دفع قيمة التذكرة"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr "تم إلغاء الطلب"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr "تذاكر الدخول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr "تذاكر سارية المفعول"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr "حاليا بالداخل"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "نعم"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr "لا"
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgctxt "widget"
|
#| msgctxt "widget"
|
||||||
@@ -395,36 +220,36 @@ msgstr ""
|
|||||||
"وصل طلبك للخادم وننتظر تنفيذه. إذا استغرق الأمر أكثر من دقيقتين تواصل معنا "
|
"وصل طلبك للخادم وننتظر تنفيذه. إذا استغرق الأمر أكثر من دقيقتين تواصل معنا "
|
||||||
"أو عاود المحاولة مجددا."
|
"أو عاود المحاولة مجددا."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr "حدث خطأ من نوع {code}."
|
msgstr "حدث خطأ من نوع {code}."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
msgstr "لم نتمكن من الاتصال بالخادم، لكن سنواصل المحاولة، رمز آخر خطأ: {code}"
|
msgstr "لم نتمكن من الاتصال بالخادم، لكن سنواصل المحاولة، رمز آخر خطأ: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr "استغرقت الطلب فترة طويلة، الرجاء المحاولة مرة أخرى."
|
msgstr "استغرقت الطلب فترة طويلة، الرجاء المحاولة مرة أخرى."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"لا يمكننا الوصول إلى الخادم حاليا، حاول مرة أخرى من فضلك. رمز الخطأ : {code}"
|
"لا يمكننا الوصول إلى الخادم حاليا، حاول مرة أخرى من فضلك. رمز الخطأ : {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr "جاري معالجة طلبك …"
|
msgstr "جاري معالجة طلبك …"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
@@ -433,11 +258,11 @@ msgstr ""
|
|||||||
"نعمل الآن على ارسال طلبك إلى الخادم، إذا أستغرقت العملية أكثر من دقيقة، يرجى "
|
"نعمل الآن على ارسال طلبك إلى الخادم، إذا أستغرقت العملية أكثر من دقيقة، يرجى "
|
||||||
"التحقق من اتصالك بالإنترنت ثم أعد تحميل الصفحة مرة أخرى."
|
"التحقق من اتصالك بالإنترنت ثم أعد تحميل الصفحة مرة أخرى."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr "أغلق الرسالة"
|
msgstr "أغلق الرسالة"
|
||||||
|
|
||||||
@@ -449,154 +274,6 @@ msgstr "تم النسخ!"
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr "للنسخ اضغط Ctrl + C!"
|
msgstr "للنسخ اضغط Ctrl + C!"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr "واحد من"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr "قبل"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr "بعد"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "منتج"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr "نوع المنتج"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr "التاريخ والوقت الحالي"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr "عدد المدخلات السابقة"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr "عدد المدخلات السابقة قبل منتصف الليل"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr "عدد المدخلات السابقة"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr "عدد المدخلات السابقة"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of days with a previous entry"
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of days with a previous entry"
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr "جميع الشروط في الأسفل"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr "خيار واحد على الأقل"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr "بداية الفعالية"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr "نهاية الفعالية"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr "تسجيل الفعالية"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr "تحديد التاريخ والوقت"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr "الوقت المحدد"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr "القدرة على التحمل (الدقائق)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr "أضف شرطا"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr "الدقائق"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr "QR الدخول"
|
msgstr "QR الدخول"
|
||||||
@@ -741,6 +418,16 @@ msgstr "غير ذلك"
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr "احسب"
|
msgstr "احسب"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "نعم"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr "لا"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
@@ -1260,6 +947,193 @@ msgstr "نوفمبر"
|
|||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr "ديسمبر"
|
msgstr "ديسمبر"
|
||||||
|
|
||||||
|
#~ msgid "Select a check-in list"
|
||||||
|
#~ msgstr "اختر قائمة الدخول"
|
||||||
|
|
||||||
|
#~ msgid "No active check-in lists found."
|
||||||
|
#~ msgstr "لم يتم العثور على قوائم دخول نشطة."
|
||||||
|
|
||||||
|
#~ msgid "Switch check-in list"
|
||||||
|
#~ msgstr "تبديل قائمة الدخول"
|
||||||
|
|
||||||
|
#~ msgid "Search results"
|
||||||
|
#~ msgstr "البحث في النتائج"
|
||||||
|
|
||||||
|
#~ msgid "No tickets found"
|
||||||
|
#~ msgstr "لم يتم العثور على تذاكر"
|
||||||
|
|
||||||
|
#~ msgid "Result"
|
||||||
|
#~ msgstr "النتيجة"
|
||||||
|
|
||||||
|
#~ msgid "This ticket requires special attention"
|
||||||
|
#~ msgstr "تحتاج هذه التذكرة إلى إهتمام خاص"
|
||||||
|
|
||||||
|
#~ msgid "Switch direction"
|
||||||
|
#~ msgstr "تغيير المسار"
|
||||||
|
|
||||||
|
#~ msgid "Entry"
|
||||||
|
#~ msgstr "دخول"
|
||||||
|
|
||||||
|
#~ msgid "Exit"
|
||||||
|
#~ msgstr "خروج"
|
||||||
|
|
||||||
|
#~ msgid "Scan a ticket or search and press return…"
|
||||||
|
#~ msgstr "قم بمسح التذكرة أو إبحث واضغط زر العودة…"
|
||||||
|
|
||||||
|
#~ msgid "Load more"
|
||||||
|
#~ msgstr "تحميل المزيد"
|
||||||
|
|
||||||
|
#~ msgid "Valid"
|
||||||
|
#~ msgstr "ساري المفعول"
|
||||||
|
|
||||||
|
#~ msgid "Unpaid"
|
||||||
|
#~ msgstr "غير مدفوع"
|
||||||
|
|
||||||
|
#~ msgid "Canceled"
|
||||||
|
#~ msgstr "ملغاة"
|
||||||
|
|
||||||
|
#~ msgid "Redeemed"
|
||||||
|
#~ msgstr "مستخدم"
|
||||||
|
|
||||||
|
#~ msgid "Cancel"
|
||||||
|
#~ msgstr "قم بالإلغاء"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not paid"
|
||||||
|
#~ msgstr "لم يتم دفع قيمة التذكرة"
|
||||||
|
|
||||||
|
#~ msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||||
|
#~ msgstr "لم يتم دفع قيمة التذكرة بعد، هل تريد المتابعة على أي حال؟"
|
||||||
|
|
||||||
|
#~ msgid "Additional information required"
|
||||||
|
#~ msgstr "مطلوب معلومات إضافية"
|
||||||
|
|
||||||
|
#~ msgid "Valid ticket"
|
||||||
|
#~ msgstr "تذكرة سارية المفعول"
|
||||||
|
|
||||||
|
#~ msgid "Exit recorded"
|
||||||
|
#~ msgstr "تم تسجيل الخروج"
|
||||||
|
|
||||||
|
#~ msgid "Ticket already used"
|
||||||
|
#~ msgstr "تم استخدام التذكرة مسبقا"
|
||||||
|
|
||||||
|
#~ msgid "Information required"
|
||||||
|
#~ msgstr "معلومات مطلوبة"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Unknown error."
|
||||||
|
#~ msgid "Unknown ticket"
|
||||||
|
#~ msgstr "خطأ غير معروف."
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Entry not allowed"
|
||||||
|
#~ msgid "Ticket type not allowed here"
|
||||||
|
#~ msgstr "إدخال غير مسموح"
|
||||||
|
|
||||||
|
#~ msgid "Entry not allowed"
|
||||||
|
#~ msgstr "إدخال غير مسموح"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code revoked/changed"
|
||||||
|
#~ msgstr "تم إلغاء رمز التذكرة أو تبديله"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Ticket not paid"
|
||||||
|
#~ msgid "Ticket blocked"
|
||||||
|
#~ msgstr "لم يتم دفع قيمة التذكرة"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Ticket not paid"
|
||||||
|
#~ msgid "Ticket not valid at this time"
|
||||||
|
#~ msgstr "لم يتم دفع قيمة التذكرة"
|
||||||
|
|
||||||
|
#~ msgid "Order canceled"
|
||||||
|
#~ msgstr "تم إلغاء الطلب"
|
||||||
|
|
||||||
|
#~ msgid "Checked-in Tickets"
|
||||||
|
#~ msgstr "تذاكر الدخول"
|
||||||
|
|
||||||
|
#~ msgid "Valid Tickets"
|
||||||
|
#~ msgstr "تذاكر سارية المفعول"
|
||||||
|
|
||||||
|
#~ msgid "Currently inside"
|
||||||
|
#~ msgstr "حاليا بالداخل"
|
||||||
|
|
||||||
|
#~ msgid "is one of"
|
||||||
|
#~ msgstr "واحد من"
|
||||||
|
|
||||||
|
#~ msgid "is before"
|
||||||
|
#~ msgstr "قبل"
|
||||||
|
|
||||||
|
#~ msgid "is after"
|
||||||
|
#~ msgstr "بعد"
|
||||||
|
|
||||||
|
#~ msgid "Product"
|
||||||
|
#~ msgstr "منتج"
|
||||||
|
|
||||||
|
#~ msgid "Product variation"
|
||||||
|
#~ msgstr "نوع المنتج"
|
||||||
|
|
||||||
|
#~ msgid "Current date and time"
|
||||||
|
#~ msgstr "التاريخ والوقت الحالي"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries"
|
||||||
|
#~ msgstr "عدد المدخلات السابقة"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since midnight"
|
||||||
|
#~ msgstr "عدد المدخلات السابقة قبل منتصف الليل"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries since"
|
||||||
|
#~ msgstr "عدد المدخلات السابقة"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries before"
|
||||||
|
#~ msgstr "عدد المدخلات السابقة"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry"
|
||||||
|
#~ msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of days with a previous entry"
|
||||||
|
#~ msgid "Number of days with a previous entry since"
|
||||||
|
#~ msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of days with a previous entry"
|
||||||
|
#~ msgid "Number of days with a previous entry before"
|
||||||
|
#~ msgstr "عدد الأيام التي تحتوي على مدخل سابق"
|
||||||
|
|
||||||
|
#~ msgid "All of the conditions below (AND)"
|
||||||
|
#~ msgstr "جميع الشروط في الأسفل"
|
||||||
|
|
||||||
|
#~ msgid "At least one of the conditions below (OR)"
|
||||||
|
#~ msgstr "خيار واحد على الأقل"
|
||||||
|
|
||||||
|
#~ msgid "Event start"
|
||||||
|
#~ msgstr "بداية الفعالية"
|
||||||
|
|
||||||
|
#~ msgid "Event end"
|
||||||
|
#~ msgstr "نهاية الفعالية"
|
||||||
|
|
||||||
|
#~ msgid "Event admission"
|
||||||
|
#~ msgstr "تسجيل الفعالية"
|
||||||
|
|
||||||
|
#~ msgid "custom date and time"
|
||||||
|
#~ msgstr "تحديد التاريخ والوقت"
|
||||||
|
|
||||||
|
#~ msgid "custom time"
|
||||||
|
#~ msgstr "الوقت المحدد"
|
||||||
|
|
||||||
|
#~ msgid "Tolerance (minutes)"
|
||||||
|
#~ msgstr "القدرة على التحمل (الدقائق)"
|
||||||
|
|
||||||
|
#~ msgid "Add condition"
|
||||||
|
#~ msgstr "أضف شرطا"
|
||||||
|
|
||||||
|
#~ msgid "minutes"
|
||||||
|
#~ msgstr "الدقائق"
|
||||||
|
|
||||||
#~ msgid "Time zone:"
|
#~ msgid "Time zone:"
|
||||||
#~ msgstr "المنطقة الزمنية:"
|
#~ msgstr "المنطقة الزمنية:"
|
||||||
|
|
||||||
|
|||||||
+1506
-1420
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -130,7 +130,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -184,172 +183,6 @@ msgstr ""
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -376,46 +209,46 @@ msgid ""
|
|||||||
"browser and try again."
|
"browser and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
"page and try again."
|
"page and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -427,146 +260,6 @@ msgstr ""
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -701,6 +394,16 @@ msgstr ""
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
|
|||||||
+1551
-1431
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: 2025-10-31 17:00+0000\n"
|
"PO-Revision-Date: 2025-10-31 17:00+0000\n"
|
||||||
"Last-Translator: Núria Masclans <nuriamasclansserrat@gmail.com>\n"
|
"Last-Translator: Núria Masclans <nuriamasclansserrat@gmail.com>\n"
|
||||||
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
|
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||||
@@ -131,7 +131,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr "Mercado Pago"
|
msgstr "Mercado Pago"
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr "Continua"
|
msgstr "Continua"
|
||||||
@@ -185,172 +184,6 @@ msgstr "Total"
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr "Contactant amb el teu banc…"
|
msgstr "Contactant amb el teu banc…"
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr "Selecciona una llista d'acreditació"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr "No s'ha trobat cap lllista d'acreditació activa."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr "Canvia la llista d'acreditació"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr "Resultats de la cerca"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr "No s'han trobat entrades"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr "Resultat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr "Aquesta entrada requereix atenció especial"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr "Canvia la direcció"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr "Entrada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr "Sortida"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr "Escaneja l'entrada o cerca i prem Retorn…"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr "Mostra'n més"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr "Vàlid"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr "No pagat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr "Cancel·lat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr "Confirmat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr "Pendent d'aprovació"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr "Reemborsat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Cancel·lar"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr "Entrada no pagada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr "Aquesta entrada no està pagada. Vols continuar igualment?"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr "Cal informació addicional"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr "Entrada vàlida"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr "Sortida registrada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr "Entrada ja utilitzada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr "Informació requerida"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr "Entrada desconeguda"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr "Tipus d'entrada no permès aquí"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr "Entrada no permesa"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr "Codi d’entrada anul·lat o modificat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr "Entrada bloquejada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr "Entrada no vàlida en aquest moment"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr "S'ha cancel·lat la comanda"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr "Codi de l’entrada ambigu a la llista"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr "Comanda no aprovada"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr "Entrades registrades"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr "Entrades vàlides"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr "Actualment dins"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "Sí"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr "No"
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr "Tanca"
|
msgstr "Tanca"
|
||||||
@@ -383,14 +216,14 @@ msgstr ""
|
|||||||
"Si aquesta acció triga més de 2 minuts, contacta'ns o torna enrere al "
|
"Si aquesta acció triga més de 2 minuts, contacta'ns o torna enrere al "
|
||||||
"navegador i prova-ho de nou."
|
"navegador i prova-ho de nou."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr "S'ha produït un error de tipus {code}."
|
msgstr "S'ha produït un error de tipus {code}."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
@@ -398,23 +231,23 @@ msgstr ""
|
|||||||
"Actualment no podem connectar amb el servidor, però seguim intentant-ho. "
|
"Actualment no podem connectar amb el servidor, però seguim intentant-ho. "
|
||||||
"Últim codi d’error: {code}"
|
"Últim codi d’error: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr "Temps d’espera esgotat. Torna-ho a provar."
|
msgstr "Temps d’espera esgotat. Torna-ho a provar."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"No es pot connectar amb el servidor. Torna-ho a provar. Codi d’error: {code}"
|
"No es pot connectar amb el servidor. Torna-ho a provar. Codi d’error: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr "Estem processant la vostra sol·licitud …"
|
msgstr "Estem processant la vostra sol·licitud …"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
@@ -423,11 +256,11 @@ msgstr ""
|
|||||||
"Hem enviat la teva petició al servidor. Si triga més d'1 minut, comprova la "
|
"Hem enviat la teva petició al servidor. Si triga més d'1 minut, comprova la "
|
||||||
"connexió, recarrega la pàgina i torna-ho a provar."
|
"connexió, recarrega la pàgina i torna-ho a provar."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr "Si triga més de pocs minuts, contacta'ns."
|
msgstr "Si triga més de pocs minuts, contacta'ns."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr "Tanca el missatge"
|
msgstr "Tanca el missatge"
|
||||||
|
|
||||||
@@ -439,146 +272,6 @@ msgstr "Copiat!"
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr "Prem Ctrl-C per copiar!"
|
msgstr "Prem Ctrl-C per copiar!"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr "forma part de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr "abans de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr "després de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr "="
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "Producte"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr "Variació del producte"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr "Porta"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr "Data i hora actuals"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr "Dia actual de la setmana (1 = Dilluns, 7 = Diumenge)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr "Estat actual de l'entrada"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr "Nombre d'entrades anteriors"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr "Nombre d’entrades anteriors des de la mitjanit"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr "Nombre d’entrades anteriors des de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr "Nombre d’entrades anteriors abans de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr "Nombre de dies amb una entrada anterior"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr "Nombre de dies amb una entrada anterior des de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr "Nombre de dies amb una entrada anterior abans de"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr "Minuts des de l'última entrada (-1 per la primera entrada)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr "Minuts des de la primera entrada (-1 a la primera entrada)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr "Complir totes les condicions següents"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr "Complir almenys una de les condicions següents"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr "Inici de l'esdeveniment"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr "Finalització de l'esdeveniment"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr "Admissió de l'esdeveniment"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr "Data i hora personalitzades"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr "Hora personalitzada"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr "Tolerància (minuts)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr "Afegeix condició"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr "en minuts"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr "Duplicat"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr "present"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr "absent"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr "Error: Producte no trobat!"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr "Error: Variació no trobada!"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr "Registre amb codi QR"
|
msgstr "Registre amb codi QR"
|
||||||
@@ -717,6 +410,16 @@ msgstr "Altres"
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr "Quantitat"
|
msgstr "Quantitat"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "Sí"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr "No"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
@@ -1193,5 +896,223 @@ msgstr ""
|
|||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#~ msgid "Select a check-in list"
|
||||||
|
#~ msgstr "Selecciona una llista d'acreditació"
|
||||||
|
|
||||||
|
#~ msgid "No active check-in lists found."
|
||||||
|
#~ msgstr "No s'ha trobat cap lllista d'acreditació activa."
|
||||||
|
|
||||||
|
#~ msgid "Switch check-in list"
|
||||||
|
#~ msgstr "Canvia la llista d'acreditació"
|
||||||
|
|
||||||
|
#~ msgid "Search results"
|
||||||
|
#~ msgstr "Resultats de la cerca"
|
||||||
|
|
||||||
|
#~ msgid "No tickets found"
|
||||||
|
#~ msgstr "No s'han trobat entrades"
|
||||||
|
|
||||||
|
#~ msgid "Result"
|
||||||
|
#~ msgstr "Resultat"
|
||||||
|
|
||||||
|
#~ msgid "This ticket requires special attention"
|
||||||
|
#~ msgstr "Aquesta entrada requereix atenció especial"
|
||||||
|
|
||||||
|
#~ msgid "Switch direction"
|
||||||
|
#~ msgstr "Canvia la direcció"
|
||||||
|
|
||||||
|
#~ msgid "Entry"
|
||||||
|
#~ msgstr "Entrada"
|
||||||
|
|
||||||
|
#~ msgid "Exit"
|
||||||
|
#~ msgstr "Sortida"
|
||||||
|
|
||||||
|
#~ msgid "Scan a ticket or search and press return…"
|
||||||
|
#~ msgstr "Escaneja l'entrada o cerca i prem Retorn…"
|
||||||
|
|
||||||
|
#~ msgid "Load more"
|
||||||
|
#~ msgstr "Mostra'n més"
|
||||||
|
|
||||||
|
#~ msgid "Valid"
|
||||||
|
#~ msgstr "Vàlid"
|
||||||
|
|
||||||
|
#~ msgid "Unpaid"
|
||||||
|
#~ msgstr "No pagat"
|
||||||
|
|
||||||
|
#~ msgid "Canceled"
|
||||||
|
#~ msgstr "Cancel·lat"
|
||||||
|
|
||||||
|
#~ msgid "Confirmed"
|
||||||
|
#~ msgstr "Confirmat"
|
||||||
|
|
||||||
|
#~ msgid "Approval pending"
|
||||||
|
#~ msgstr "Pendent d'aprovació"
|
||||||
|
|
||||||
|
#~ msgid "Redeemed"
|
||||||
|
#~ msgstr "Reemborsat"
|
||||||
|
|
||||||
|
#~ msgid "Cancel"
|
||||||
|
#~ msgstr "Cancel·lar"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not paid"
|
||||||
|
#~ msgstr "Entrada no pagada"
|
||||||
|
|
||||||
|
#~ msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||||
|
#~ msgstr "Aquesta entrada no està pagada. Vols continuar igualment?"
|
||||||
|
|
||||||
|
#~ msgid "Additional information required"
|
||||||
|
#~ msgstr "Cal informació addicional"
|
||||||
|
|
||||||
|
#~ msgid "Valid ticket"
|
||||||
|
#~ msgstr "Entrada vàlida"
|
||||||
|
|
||||||
|
#~ msgid "Exit recorded"
|
||||||
|
#~ msgstr "Sortida registrada"
|
||||||
|
|
||||||
|
#~ msgid "Ticket already used"
|
||||||
|
#~ msgstr "Entrada ja utilitzada"
|
||||||
|
|
||||||
|
#~ msgid "Information required"
|
||||||
|
#~ msgstr "Informació requerida"
|
||||||
|
|
||||||
|
#~ msgid "Unknown ticket"
|
||||||
|
#~ msgstr "Entrada desconeguda"
|
||||||
|
|
||||||
|
#~ msgid "Ticket type not allowed here"
|
||||||
|
#~ msgstr "Tipus d'entrada no permès aquí"
|
||||||
|
|
||||||
|
#~ msgid "Entry not allowed"
|
||||||
|
#~ msgstr "Entrada no permesa"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code revoked/changed"
|
||||||
|
#~ msgstr "Codi d’entrada anul·lat o modificat"
|
||||||
|
|
||||||
|
#~ msgid "Ticket blocked"
|
||||||
|
#~ msgstr "Entrada bloquejada"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not valid at this time"
|
||||||
|
#~ msgstr "Entrada no vàlida en aquest moment"
|
||||||
|
|
||||||
|
#~ msgid "Order canceled"
|
||||||
|
#~ msgstr "S'ha cancel·lat la comanda"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code is ambiguous on list"
|
||||||
|
#~ msgstr "Codi de l’entrada ambigu a la llista"
|
||||||
|
|
||||||
|
#~ msgid "Order not approved"
|
||||||
|
#~ msgstr "Comanda no aprovada"
|
||||||
|
|
||||||
|
#~ msgid "Checked-in Tickets"
|
||||||
|
#~ msgstr "Entrades registrades"
|
||||||
|
|
||||||
|
#~ msgid "Valid Tickets"
|
||||||
|
#~ msgstr "Entrades vàlides"
|
||||||
|
|
||||||
|
#~ msgid "Currently inside"
|
||||||
|
#~ msgstr "Actualment dins"
|
||||||
|
|
||||||
|
#~ msgid "is one of"
|
||||||
|
#~ msgstr "forma part de"
|
||||||
|
|
||||||
|
#~ msgid "is before"
|
||||||
|
#~ msgstr "abans de"
|
||||||
|
|
||||||
|
#~ msgid "is after"
|
||||||
|
#~ msgstr "després de"
|
||||||
|
|
||||||
|
#~ msgid "="
|
||||||
|
#~ msgstr "="
|
||||||
|
|
||||||
|
#~ msgid "Product"
|
||||||
|
#~ msgstr "Producte"
|
||||||
|
|
||||||
|
#~ msgid "Product variation"
|
||||||
|
#~ msgstr "Variació del producte"
|
||||||
|
|
||||||
|
#~ msgid "Gate"
|
||||||
|
#~ msgstr "Porta"
|
||||||
|
|
||||||
|
#~ msgid "Current date and time"
|
||||||
|
#~ msgstr "Data i hora actuals"
|
||||||
|
|
||||||
|
#~ msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||||
|
#~ msgstr "Dia actual de la setmana (1 = Dilluns, 7 = Diumenge)"
|
||||||
|
|
||||||
|
#~ msgid "Current entry status"
|
||||||
|
#~ msgstr "Estat actual de l'entrada"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries"
|
||||||
|
#~ msgstr "Nombre d'entrades anteriors"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since midnight"
|
||||||
|
#~ msgstr "Nombre d’entrades anteriors des de la mitjanit"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since"
|
||||||
|
#~ msgstr "Nombre d’entrades anteriors des de"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries before"
|
||||||
|
#~ msgstr "Nombre d’entrades anteriors abans de"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry"
|
||||||
|
#~ msgstr "Nombre de dies amb una entrada anterior"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry since"
|
||||||
|
#~ msgstr "Nombre de dies amb una entrada anterior des de"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry before"
|
||||||
|
#~ msgstr "Nombre de dies amb una entrada anterior abans de"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since last entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuts des de l'última entrada (-1 per la primera entrada)"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since first entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuts des de la primera entrada (-1 a la primera entrada)"
|
||||||
|
|
||||||
|
#~ msgid "All of the conditions below (AND)"
|
||||||
|
#~ msgstr "Complir totes les condicions següents"
|
||||||
|
|
||||||
|
#~ msgid "At least one of the conditions below (OR)"
|
||||||
|
#~ msgstr "Complir almenys una de les condicions següents"
|
||||||
|
|
||||||
|
#~ msgid "Event start"
|
||||||
|
#~ msgstr "Inici de l'esdeveniment"
|
||||||
|
|
||||||
|
#~ msgid "Event end"
|
||||||
|
#~ msgstr "Finalització de l'esdeveniment"
|
||||||
|
|
||||||
|
#~ msgid "Event admission"
|
||||||
|
#~ msgstr "Admissió de l'esdeveniment"
|
||||||
|
|
||||||
|
#~ msgid "custom date and time"
|
||||||
|
#~ msgstr "Data i hora personalitzades"
|
||||||
|
|
||||||
|
#~ msgid "custom time"
|
||||||
|
#~ msgstr "Hora personalitzada"
|
||||||
|
|
||||||
|
#~ msgid "Tolerance (minutes)"
|
||||||
|
#~ msgstr "Tolerància (minuts)"
|
||||||
|
|
||||||
|
#~ msgid "Add condition"
|
||||||
|
#~ msgstr "Afegeix condició"
|
||||||
|
|
||||||
|
#~ msgid "minutes"
|
||||||
|
#~ msgstr "en minuts"
|
||||||
|
|
||||||
|
#~ msgid "Duplicate"
|
||||||
|
#~ msgstr "Duplicat"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "present"
|
||||||
|
#~ msgstr "present"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "absent"
|
||||||
|
#~ msgstr "absent"
|
||||||
|
|
||||||
|
#~ msgid "Error: Product not found!"
|
||||||
|
#~ msgstr "Error: Producte no trobat!"
|
||||||
|
|
||||||
|
#~ msgid "Error: Variation not found!"
|
||||||
|
#~ msgstr "Error: Variació no trobada!"
|
||||||
|
|
||||||
#~ msgid "iDEAL"
|
#~ msgid "iDEAL"
|
||||||
#~ msgstr "iDEAL"
|
#~ msgstr "iDEAL"
|
||||||
|
|||||||
+1577
-1430
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: 2026-01-08 04:00+0000\n"
|
"PO-Revision-Date: 2026-01-08 04:00+0000\n"
|
||||||
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
||||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||||
@@ -131,7 +131,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr "Mercado Pago"
|
msgstr "Mercado Pago"
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr "Pokračovat"
|
msgstr "Pokračovat"
|
||||||
@@ -185,172 +184,6 @@ msgstr "Celkem"
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr "Kontaktuji vaši banku …"
|
msgstr "Kontaktuji vaši banku …"
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr "Zvolte check-in list"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr "Žádné aktivní check-in listy."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr "Změnit check-in list"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr "Vyhledat výsledky"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr "Nenalezeny žádné lístky"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr "Výsledek"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr "Tato vstupenka vyžaduje speciální pozornost"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr "Změnit směr"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr "Vstup"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr "Výstup"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr "Naskenujte vstupenku, nebo ji vyhledejte a zmáčkněte zpět…"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr "Načíst více"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr "Potrvzeno"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr "Nezaplaceno"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr "Zrušeno"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr "Potvrzeno"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr "Čeká na schválení"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr "Uplatněno"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Zrušit"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr "Vstupenka není zaplacena"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr "Vstupenka nebyla zaplacena. Chcete i přesto pokračovat?"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr "Potřebné další informace"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr "Platná vstupenka"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr "Opustit nahrávané"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr "Vstupenka již byla použita"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr "Informace vyžadována"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr "Neznámá vstupenka"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr "Typ vstupenky zde není povolen"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr "Vstup není povolen"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr "Kód vstupenky změněn"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr "Vstupenka zablokována"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr "Vstupenka je v tuto chvíli neplatná"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr "Objednávka zrušena"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr "Kód vstupenky je v seznamu nejednoznačný"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr "Objednávka nebyla potvrzena"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr "Vyřízené vstupenky"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr "Platné vstupenky"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr "Aktuálně uvnitř"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "Ano"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr "Ne"
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr "zavřít"
|
msgstr "zavřít"
|
||||||
@@ -382,14 +215,14 @@ msgstr ""
|
|||||||
"Pokud to trvá více jak dvě minuty, prosím kontaktuje nás nebo se vraťte do "
|
"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."
|
"vašeho prohlížeče a zkuste to znovu."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr "Vyskytla se chyba {code}."
|
msgstr "Vyskytla se chyba {code}."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
@@ -397,12 +230,12 @@ msgstr ""
|
|||||||
"Momentálně nemůžeme kontaktovat server, ale stále se o to pokoušíme. "
|
"Momentálně nemůžeme kontaktovat server, ale stále se o to pokoušíme. "
|
||||||
"Poslední chybový kód: {code}"
|
"Poslední chybový kód: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr "Zpracování požadavku trvá příliš dlouho. Prosím zkuste to znovu."
|
msgstr "Zpracování požadavku trvá příliš dlouho. Prosím zkuste to znovu."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
@@ -410,11 +243,11 @@ msgstr ""
|
|||||||
"Momentálně nemůžeme kontaktovat server. Prosím zkuste to znovu. Chybový kód: "
|
"Momentálně nemůžeme kontaktovat server. Prosím zkuste to znovu. Chybový kód: "
|
||||||
"{code}"
|
"{code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr "Zpracováváme váš požadavek …"
|
msgstr "Zpracováváme váš požadavek …"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
@@ -424,11 +257,11 @@ msgstr ""
|
|||||||
"prosím zkontrolujte své internetové připojení a znovu načtěte stránku a "
|
"prosím zkontrolujte své internetové připojení a znovu načtěte stránku a "
|
||||||
"zkuste to znovu."
|
"zkuste to znovu."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr "Pokud akce trvá déle než několik minut, kontaktujte nás."
|
msgstr "Pokud akce trvá déle než několik minut, kontaktujte nás."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr "Zavřít zprávu"
|
msgstr "Zavřít zprávu"
|
||||||
|
|
||||||
@@ -440,154 +273,6 @@ msgstr "Zkopírováno!"
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr "Stiskněte Ctrl-C pro zkopírování!"
|
msgstr "Stiskněte Ctrl-C pro zkopírování!"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr "je jedním z"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr "je před"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr "je po"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr "="
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "Produkt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr "Varianta produktu"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr "Brána"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr "Současný čas"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr "Aktuální den týdne (1 = pondělí, 7 = neděle)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr "Počet předchozích záznamů"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr "Počet záznamů od půlnoci"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr "Počet předchozích záznamů"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr "Počet předchozích záznamů"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr "Počet dní bez úprav"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of days with a previous entry"
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr "Počet dní bez úprav"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of days with a previous entry"
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr "Počet dní bez úprav"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr "Minuty od předchozího vstupu (-1 pro první vstup)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr "Minuty od prvního vstupu (-1 pro první vstup)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr "Všechny následující podmínky (AND)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr "Alespoň jedna z následujících podmínek (OR)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr "Začátek akce"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr "Konec akce"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr "Vstup na akci"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr "Pevný termín"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr "Pevná doba"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr "Tolerance (v minutách)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr "Přidat podmínku"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr "minuty"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr "Duplikát"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr "přítomen"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr "nepřítomen"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr "Check-in QR kód"
|
msgstr "Check-in QR kód"
|
||||||
@@ -727,6 +412,16 @@ msgstr "Další"
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr "Počet"
|
msgstr "Počet"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "Ano"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr "Ne"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
@@ -1220,6 +915,223 @@ msgstr "Listopad"
|
|||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr "Prosinec"
|
msgstr "Prosinec"
|
||||||
|
|
||||||
|
#~ msgid "Select a check-in list"
|
||||||
|
#~ msgstr "Zvolte check-in list"
|
||||||
|
|
||||||
|
#~ msgid "No active check-in lists found."
|
||||||
|
#~ msgstr "Žádné aktivní check-in listy."
|
||||||
|
|
||||||
|
#~ msgid "Switch check-in list"
|
||||||
|
#~ msgstr "Změnit check-in list"
|
||||||
|
|
||||||
|
#~ msgid "Search results"
|
||||||
|
#~ msgstr "Vyhledat výsledky"
|
||||||
|
|
||||||
|
#~ msgid "No tickets found"
|
||||||
|
#~ msgstr "Nenalezeny žádné lístky"
|
||||||
|
|
||||||
|
#~ msgid "Result"
|
||||||
|
#~ msgstr "Výsledek"
|
||||||
|
|
||||||
|
#~ msgid "This ticket requires special attention"
|
||||||
|
#~ msgstr "Tato vstupenka vyžaduje speciální pozornost"
|
||||||
|
|
||||||
|
#~ msgid "Switch direction"
|
||||||
|
#~ msgstr "Změnit směr"
|
||||||
|
|
||||||
|
#~ msgid "Entry"
|
||||||
|
#~ msgstr "Vstup"
|
||||||
|
|
||||||
|
#~ msgid "Exit"
|
||||||
|
#~ msgstr "Výstup"
|
||||||
|
|
||||||
|
#~ msgid "Scan a ticket or search and press return…"
|
||||||
|
#~ msgstr "Naskenujte vstupenku, nebo ji vyhledejte a zmáčkněte zpět…"
|
||||||
|
|
||||||
|
#~ msgid "Load more"
|
||||||
|
#~ msgstr "Načíst více"
|
||||||
|
|
||||||
|
#~ msgid "Valid"
|
||||||
|
#~ msgstr "Potrvzeno"
|
||||||
|
|
||||||
|
#~ msgid "Unpaid"
|
||||||
|
#~ msgstr "Nezaplaceno"
|
||||||
|
|
||||||
|
#~ msgid "Canceled"
|
||||||
|
#~ msgstr "Zrušeno"
|
||||||
|
|
||||||
|
#~ msgid "Confirmed"
|
||||||
|
#~ msgstr "Potvrzeno"
|
||||||
|
|
||||||
|
#~ msgid "Approval pending"
|
||||||
|
#~ msgstr "Čeká na schválení"
|
||||||
|
|
||||||
|
#~ msgid "Redeemed"
|
||||||
|
#~ msgstr "Uplatněno"
|
||||||
|
|
||||||
|
#~ msgid "Cancel"
|
||||||
|
#~ msgstr "Zrušit"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not paid"
|
||||||
|
#~ msgstr "Vstupenka není zaplacena"
|
||||||
|
|
||||||
|
#~ msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||||
|
#~ msgstr "Vstupenka nebyla zaplacena. Chcete i přesto pokračovat?"
|
||||||
|
|
||||||
|
#~ msgid "Additional information required"
|
||||||
|
#~ msgstr "Potřebné další informace"
|
||||||
|
|
||||||
|
#~ msgid "Valid ticket"
|
||||||
|
#~ msgstr "Platná vstupenka"
|
||||||
|
|
||||||
|
#~ msgid "Exit recorded"
|
||||||
|
#~ msgstr "Opustit nahrávané"
|
||||||
|
|
||||||
|
#~ msgid "Ticket already used"
|
||||||
|
#~ msgstr "Vstupenka již byla použita"
|
||||||
|
|
||||||
|
#~ msgid "Information required"
|
||||||
|
#~ msgstr "Informace vyžadována"
|
||||||
|
|
||||||
|
#~ msgid "Unknown ticket"
|
||||||
|
#~ msgstr "Neznámá vstupenka"
|
||||||
|
|
||||||
|
#~ msgid "Ticket type not allowed here"
|
||||||
|
#~ msgstr "Typ vstupenky zde není povolen"
|
||||||
|
|
||||||
|
#~ msgid "Entry not allowed"
|
||||||
|
#~ msgstr "Vstup není povolen"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code revoked/changed"
|
||||||
|
#~ msgstr "Kód vstupenky změněn"
|
||||||
|
|
||||||
|
#~ msgid "Ticket blocked"
|
||||||
|
#~ msgstr "Vstupenka zablokována"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not valid at this time"
|
||||||
|
#~ msgstr "Vstupenka je v tuto chvíli neplatná"
|
||||||
|
|
||||||
|
#~ msgid "Order canceled"
|
||||||
|
#~ msgstr "Objednávka zrušena"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code is ambiguous on list"
|
||||||
|
#~ msgstr "Kód vstupenky je v seznamu nejednoznačný"
|
||||||
|
|
||||||
|
#~ msgid "Order not approved"
|
||||||
|
#~ msgstr "Objednávka nebyla potvrzena"
|
||||||
|
|
||||||
|
#~ msgid "Checked-in Tickets"
|
||||||
|
#~ msgstr "Vyřízené vstupenky"
|
||||||
|
|
||||||
|
#~ msgid "Valid Tickets"
|
||||||
|
#~ msgstr "Platné vstupenky"
|
||||||
|
|
||||||
|
#~ msgid "Currently inside"
|
||||||
|
#~ msgstr "Aktuálně uvnitř"
|
||||||
|
|
||||||
|
#~ msgid "is one of"
|
||||||
|
#~ msgstr "je jedním z"
|
||||||
|
|
||||||
|
#~ msgid "is before"
|
||||||
|
#~ msgstr "je před"
|
||||||
|
|
||||||
|
#~ msgid "is after"
|
||||||
|
#~ msgstr "je po"
|
||||||
|
|
||||||
|
#~ msgid "="
|
||||||
|
#~ msgstr "="
|
||||||
|
|
||||||
|
#~ msgid "Product"
|
||||||
|
#~ msgstr "Produkt"
|
||||||
|
|
||||||
|
#~ msgid "Product variation"
|
||||||
|
#~ msgstr "Varianta produktu"
|
||||||
|
|
||||||
|
#~ msgid "Gate"
|
||||||
|
#~ msgstr "Brána"
|
||||||
|
|
||||||
|
#~ msgid "Current date and time"
|
||||||
|
#~ msgstr "Současný čas"
|
||||||
|
|
||||||
|
#~ msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||||
|
#~ msgstr "Aktuální den týdne (1 = pondělí, 7 = neděle)"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries"
|
||||||
|
#~ msgstr "Počet předchozích záznamů"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since midnight"
|
||||||
|
#~ msgstr "Počet záznamů od půlnoci"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries since"
|
||||||
|
#~ msgstr "Počet předchozích záznamů"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries before"
|
||||||
|
#~ msgstr "Počet předchozích záznamů"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry"
|
||||||
|
#~ msgstr "Počet dní bez úprav"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of days with a previous entry"
|
||||||
|
#~ msgid "Number of days with a previous entry since"
|
||||||
|
#~ msgstr "Počet dní bez úprav"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of days with a previous entry"
|
||||||
|
#~ msgid "Number of days with a previous entry before"
|
||||||
|
#~ msgstr "Počet dní bez úprav"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since last entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuty od předchozího vstupu (-1 pro první vstup)"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since first entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuty od prvního vstupu (-1 pro první vstup)"
|
||||||
|
|
||||||
|
#~ msgid "All of the conditions below (AND)"
|
||||||
|
#~ msgstr "Všechny následující podmínky (AND)"
|
||||||
|
|
||||||
|
#~ msgid "At least one of the conditions below (OR)"
|
||||||
|
#~ msgstr "Alespoň jedna z následujících podmínek (OR)"
|
||||||
|
|
||||||
|
#~ msgid "Event start"
|
||||||
|
#~ msgstr "Začátek akce"
|
||||||
|
|
||||||
|
#~ msgid "Event end"
|
||||||
|
#~ msgstr "Konec akce"
|
||||||
|
|
||||||
|
#~ msgid "Event admission"
|
||||||
|
#~ msgstr "Vstup na akci"
|
||||||
|
|
||||||
|
#~ msgid "custom date and time"
|
||||||
|
#~ msgstr "Pevný termín"
|
||||||
|
|
||||||
|
#~ msgid "custom time"
|
||||||
|
#~ msgstr "Pevná doba"
|
||||||
|
|
||||||
|
#~ msgid "Tolerance (minutes)"
|
||||||
|
#~ msgstr "Tolerance (v minutách)"
|
||||||
|
|
||||||
|
#~ msgid "Add condition"
|
||||||
|
#~ msgstr "Přidat podmínku"
|
||||||
|
|
||||||
|
#~ msgid "minutes"
|
||||||
|
#~ msgstr "minuty"
|
||||||
|
|
||||||
|
#~ msgid "Duplicate"
|
||||||
|
#~ msgstr "Duplikát"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "present"
|
||||||
|
#~ msgstr "přítomen"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "absent"
|
||||||
|
#~ msgstr "nepřítomen"
|
||||||
|
|
||||||
#~ msgid "iDEAL"
|
#~ msgid "iDEAL"
|
||||||
#~ msgstr "iDEAL"
|
#~ msgstr "iDEAL"
|
||||||
|
|
||||||
|
|||||||
+1520
-1420
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -131,7 +131,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -185,172 +184,6 @@ msgstr ""
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -377,46 +210,46 @@ msgid ""
|
|||||||
"browser and try again."
|
"browser and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
"page and try again."
|
"page and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -428,146 +261,6 @@ msgstr ""
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -702,6 +395,16 @@ msgstr ""
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
|
|||||||
+1818
-1655
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: 2026-04-22 18:00+0000\n"
|
"PO-Revision-Date: 2026-04-22 18:00+0000\n"
|
||||||
"Last-Translator: Nikolai <nikolai@lengefeldt.de>\n"
|
"Last-Translator: Nikolai <nikolai@lengefeldt.de>\n"
|
||||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||||
@@ -132,7 +132,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgctxt "widget"
|
#| msgctxt "widget"
|
||||||
@@ -189,177 +188,6 @@ msgstr "Total"
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr "Kontakter din bank …"
|
msgstr "Kontakter din bank …"
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr "Vælg en check-in liste"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr "Der blev ikke fundet nogen aktive check-in lister."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr "Skift check-in liste"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr "Søgeresultater"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr "Ingen billetter fundet"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr "Resultat"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr "Denne billet kræver særlig opmærksomhed"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr "Skift retning"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr "Indgang"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr "Udgang"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr "Scan en billet eller søg og tryk på retur…"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr "Hent flere"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr "Gyldig"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr "Ubetalt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr "Annulleret"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
#, fuzzy
|
|
||||||
#| msgctxt "widget"
|
|
||||||
#| msgid "Redeem"
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr "Indløs"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr "Billet ikke betalt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr "Gyldig billet"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr "Billet allerede i brug"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr "Kræver information"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr "Ukendt billet"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr "Billettype er ikke tilladt her"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr "Adgang ikke tilladt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr "Billetkode trukket tilbage/ændret"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr "Billet blokeret"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr "Billetten er ikke gyldig på dette tidspunkt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr "Bestilling annulleret"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr "Billetkoden er flertydig på listen"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr "Bestilling ikke godkendt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Check-in QR"
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr "Check-in QR"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr "Gyldige billetter"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr "Inde i øjeblikket"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "Ja"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr "Nej"
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgctxt "widget"
|
#| msgctxt "widget"
|
||||||
@@ -405,14 +233,14 @@ msgstr ""
|
|||||||
"Din forespørgsel er under behandling. Hvis der går mere end to minutter, så "
|
"Din forespørgsel er under behandling. Hvis der går mere end to minutter, så "
|
||||||
"kontakt os eller gå tilbage og prøv igen."
|
"kontakt os eller gå tilbage og prøv igen."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr "Der er sket en fejl ({code})."
|
msgstr "Der er sket en fejl ({code})."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
@@ -420,12 +248,12 @@ msgstr ""
|
|||||||
"Vi kan ikke komme i kontakt med serveren, men prøver igen. Seneste fejlkode: "
|
"Vi kan ikke komme i kontakt med serveren, men prøver igen. Seneste fejlkode: "
|
||||||
"{code}"
|
"{code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr "Forespørgslen tog for lang tid. Prøv igen."
|
msgstr "Forespørgslen tog for lang tid. Prøv igen."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
@@ -433,11 +261,11 @@ msgstr ""
|
|||||||
"Vi kan i øjeblikket ikke komme i kontakt med serveren. Prøv igen. Fejlkode: "
|
"Vi kan i øjeblikket ikke komme i kontakt med serveren. Prøv igen. Fejlkode: "
|
||||||
"{code}"
|
"{code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr "Vi behandler din bestilling …"
|
msgstr "Vi behandler din bestilling …"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
@@ -446,11 +274,11 @@ msgstr ""
|
|||||||
"Din forespørgsel bliver sendt til serveren. Hvis det tager mere end et "
|
"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."
|
"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:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr "Luk besked"
|
msgstr "Luk besked"
|
||||||
|
|
||||||
@@ -462,154 +290,6 @@ msgstr "Kopieret!"
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr "Tryk Ctrl-C eller ⌘-C for at kopiere!"
|
msgstr "Tryk Ctrl-C eller ⌘-C for at kopiere!"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr "er en af"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr "er før"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr "er efter"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "Produkt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr "Produktvariation"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr "Indgang"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr "Aktuel dato og klokkeslæt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr "Aktuel ugedag (1 = mandag, 7 = søndag)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr "Antal tidligere poster"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr "Antal tidligere poster"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr "Antal tidligere poster"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr "Antal tidligere poster"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Number of previous entries"
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr "Antal tidligere poster"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr "Adgang til arrangementet"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr "Check-in QR"
|
msgstr "Check-in QR"
|
||||||
@@ -755,6 +435,16 @@ msgstr "Andre"
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr "Antal"
|
msgstr "Antal"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "Ja"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr "Nej"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
@@ -1271,6 +961,157 @@ msgstr "November"
|
|||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr "December"
|
msgstr "December"
|
||||||
|
|
||||||
|
#~ msgid "Select a check-in list"
|
||||||
|
#~ msgstr "Vælg en check-in liste"
|
||||||
|
|
||||||
|
#~ msgid "No active check-in lists found."
|
||||||
|
#~ msgstr "Der blev ikke fundet nogen aktive check-in lister."
|
||||||
|
|
||||||
|
#~ msgid "Switch check-in list"
|
||||||
|
#~ msgstr "Skift check-in liste"
|
||||||
|
|
||||||
|
#~ msgid "Search results"
|
||||||
|
#~ msgstr "Søgeresultater"
|
||||||
|
|
||||||
|
#~ msgid "No tickets found"
|
||||||
|
#~ msgstr "Ingen billetter fundet"
|
||||||
|
|
||||||
|
#~ msgid "Result"
|
||||||
|
#~ msgstr "Resultat"
|
||||||
|
|
||||||
|
#~ msgid "This ticket requires special attention"
|
||||||
|
#~ msgstr "Denne billet kræver særlig opmærksomhed"
|
||||||
|
|
||||||
|
#~ msgid "Switch direction"
|
||||||
|
#~ msgstr "Skift retning"
|
||||||
|
|
||||||
|
#~ msgid "Entry"
|
||||||
|
#~ msgstr "Indgang"
|
||||||
|
|
||||||
|
#~ msgid "Exit"
|
||||||
|
#~ msgstr "Udgang"
|
||||||
|
|
||||||
|
#~ msgid "Scan a ticket or search and press return…"
|
||||||
|
#~ msgstr "Scan en billet eller søg og tryk på retur…"
|
||||||
|
|
||||||
|
#~ msgid "Load more"
|
||||||
|
#~ msgstr "Hent flere"
|
||||||
|
|
||||||
|
#~ msgid "Valid"
|
||||||
|
#~ msgstr "Gyldig"
|
||||||
|
|
||||||
|
#~ msgid "Unpaid"
|
||||||
|
#~ msgstr "Ubetalt"
|
||||||
|
|
||||||
|
#~ msgid "Canceled"
|
||||||
|
#~ msgstr "Annulleret"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgctxt "widget"
|
||||||
|
#~| msgid "Redeem"
|
||||||
|
#~ msgid "Redeemed"
|
||||||
|
#~ msgstr "Indløs"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not paid"
|
||||||
|
#~ msgstr "Billet ikke betalt"
|
||||||
|
|
||||||
|
#~ msgid "Valid ticket"
|
||||||
|
#~ msgstr "Gyldig billet"
|
||||||
|
|
||||||
|
#~ msgid "Ticket already used"
|
||||||
|
#~ msgstr "Billet allerede i brug"
|
||||||
|
|
||||||
|
#~ msgid "Information required"
|
||||||
|
#~ msgstr "Kræver information"
|
||||||
|
|
||||||
|
#~ msgid "Unknown ticket"
|
||||||
|
#~ msgstr "Ukendt billet"
|
||||||
|
|
||||||
|
#~ msgid "Ticket type not allowed here"
|
||||||
|
#~ msgstr "Billettype er ikke tilladt her"
|
||||||
|
|
||||||
|
#~ msgid "Entry not allowed"
|
||||||
|
#~ msgstr "Adgang ikke tilladt"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code revoked/changed"
|
||||||
|
#~ msgstr "Billetkode trukket tilbage/ændret"
|
||||||
|
|
||||||
|
#~ msgid "Ticket blocked"
|
||||||
|
#~ msgstr "Billet blokeret"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not valid at this time"
|
||||||
|
#~ msgstr "Billetten er ikke gyldig på dette tidspunkt"
|
||||||
|
|
||||||
|
#~ msgid "Order canceled"
|
||||||
|
#~ msgstr "Bestilling annulleret"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code is ambiguous on list"
|
||||||
|
#~ msgstr "Billetkoden er flertydig på listen"
|
||||||
|
|
||||||
|
#~ msgid "Order not approved"
|
||||||
|
#~ msgstr "Bestilling ikke godkendt"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Check-in QR"
|
||||||
|
#~ msgid "Checked-in Tickets"
|
||||||
|
#~ msgstr "Check-in QR"
|
||||||
|
|
||||||
|
#~ msgid "Valid Tickets"
|
||||||
|
#~ msgstr "Gyldige billetter"
|
||||||
|
|
||||||
|
#~ msgid "Currently inside"
|
||||||
|
#~ msgstr "Inde i øjeblikket"
|
||||||
|
|
||||||
|
#~ msgid "is one of"
|
||||||
|
#~ msgstr "er en af"
|
||||||
|
|
||||||
|
#~ msgid "is before"
|
||||||
|
#~ msgstr "er før"
|
||||||
|
|
||||||
|
#~ msgid "is after"
|
||||||
|
#~ msgstr "er efter"
|
||||||
|
|
||||||
|
#~ msgid "Product"
|
||||||
|
#~ msgstr "Produkt"
|
||||||
|
|
||||||
|
#~ msgid "Product variation"
|
||||||
|
#~ msgstr "Produktvariation"
|
||||||
|
|
||||||
|
#~ msgid "Gate"
|
||||||
|
#~ msgstr "Indgang"
|
||||||
|
|
||||||
|
#~ msgid "Current date and time"
|
||||||
|
#~ msgstr "Aktuel dato og klokkeslæt"
|
||||||
|
|
||||||
|
#~ msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||||
|
#~ msgstr "Aktuel ugedag (1 = mandag, 7 = søndag)"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries"
|
||||||
|
#~ msgstr "Antal tidligere poster"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries since"
|
||||||
|
#~ msgstr "Antal tidligere poster"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of previous entries before"
|
||||||
|
#~ msgstr "Antal tidligere poster"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of days with a previous entry since"
|
||||||
|
#~ msgstr "Antal tidligere poster"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Number of previous entries"
|
||||||
|
#~ msgid "Number of days with a previous entry before"
|
||||||
|
#~ msgstr "Antal tidligere poster"
|
||||||
|
|
||||||
|
#~ msgid "Event admission"
|
||||||
|
#~ msgstr "Adgang til arrangementet"
|
||||||
|
|
||||||
#~ msgid "iDEAL"
|
#~ msgid "iDEAL"
|
||||||
#~ msgstr "iDEAL"
|
#~ msgstr "iDEAL"
|
||||||
|
|
||||||
|
|||||||
+1584
-1443
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||||
"PO-Revision-Date: 2026-03-17 14:27+0000\n"
|
"PO-Revision-Date: 2026-03-17 14:27+0000\n"
|
||||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||||
@@ -131,7 +131,6 @@ msgid "Mercado Pago"
|
|||||||
msgstr "Mercado Pago"
|
msgstr "Mercado Pago"
|
||||||
|
|
||||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
|
||||||
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
#: pretix/static/pretixpresale/js/ui/cart.js:89
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr "Fortfahren"
|
msgstr "Fortfahren"
|
||||||
@@ -185,172 +184,6 @@ msgstr "Gesamt"
|
|||||||
msgid "Contacting your bank …"
|
msgid "Contacting your bank …"
|
||||||
msgstr "Kontaktiere Ihre Bank …"
|
msgstr "Kontaktiere Ihre Bank …"
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
|
||||||
msgid "Select a check-in list"
|
|
||||||
msgstr "Wählen Sie eine Check-In Liste"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
|
||||||
msgid "No active check-in lists found."
|
|
||||||
msgstr "Keine aktive Check-In Liste gefunden."
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
|
||||||
msgid "Switch check-in list"
|
|
||||||
msgstr "Check-In Liste wechseln"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
|
||||||
msgid "Search results"
|
|
||||||
msgstr "Suchergebnisse"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
|
||||||
msgid "No tickets found"
|
|
||||||
msgstr "Keine Tickets gefunden"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
|
||||||
msgid "Result"
|
|
||||||
msgstr "Ergebnis"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
|
||||||
msgid "This ticket requires special attention"
|
|
||||||
msgstr "Dieses Ticket benötigt besondere Aufmerksamkeit"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
|
||||||
msgid "Switch direction"
|
|
||||||
msgstr "Richtung wechseln"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
|
||||||
msgid "Entry"
|
|
||||||
msgstr "Eingang"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
|
||||||
msgid "Exit"
|
|
||||||
msgstr "Ausgang"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
|
||||||
msgid "Scan a ticket or search and press return…"
|
|
||||||
msgstr "Ticket scannen oder suchen und mit Enter bestätigen…"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
|
||||||
msgid "Load more"
|
|
||||||
msgstr "Mehr laden"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
|
|
||||||
msgid "Valid"
|
|
||||||
msgstr "Gültig"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:43
|
|
||||||
msgid "Unpaid"
|
|
||||||
msgstr "Unbezahlt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:44
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:45
|
|
||||||
msgid "Canceled"
|
|
||||||
msgstr "storniert"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
|
||||||
msgid "Confirmed"
|
|
||||||
msgstr "bestätigt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
|
||||||
msgid "Approval pending"
|
|
||||||
msgstr "Freigabe ausstehend"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
|
||||||
msgid "Redeemed"
|
|
||||||
msgstr "Eingelöst"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Abbrechen"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
|
||||||
msgid "Ticket not paid"
|
|
||||||
msgstr "Ticket nicht bezahlt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
|
||||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
|
||||||
msgstr "Dieses Ticket ist noch nicht bezahlt. Möchten Sie dennoch fortfahren?"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
|
||||||
msgid "Additional information required"
|
|
||||||
msgstr "Zusätzliche Informationen benötigt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
|
||||||
msgid "Valid ticket"
|
|
||||||
msgstr "Gültiges Ticket"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
|
||||||
msgid "Exit recorded"
|
|
||||||
msgstr "Ausgang gespeichert"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
|
||||||
msgid "Ticket already used"
|
|
||||||
msgstr "Ticket bereits eingelöst"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
|
||||||
msgid "Information required"
|
|
||||||
msgstr "Infos benötigt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
|
||||||
msgid "Unknown ticket"
|
|
||||||
msgstr "Unbekanntes Ticket"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
|
||||||
msgid "Ticket type not allowed here"
|
|
||||||
msgstr "Ticketart hier nicht erlaubt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
|
||||||
msgid "Entry not allowed"
|
|
||||||
msgstr "Eingang nicht erlaubt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
|
||||||
msgid "Ticket code revoked/changed"
|
|
||||||
msgstr "Ticket-Code gesperrt/geändert"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
|
||||||
msgid "Ticket blocked"
|
|
||||||
msgstr "Ticket gesperrt"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
|
||||||
msgid "Ticket not valid at this time"
|
|
||||||
msgstr "Ticket aktuell nicht gültig"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
|
||||||
msgid "Order canceled"
|
|
||||||
msgstr "Bestellung storniert"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
|
||||||
msgid "Ticket code is ambiguous on list"
|
|
||||||
msgstr "Ticket-Code ist nicht eindeutig auf der Liste"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
|
||||||
msgid "Order not approved"
|
|
||||||
msgstr "Bestellung nicht freigegeben"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
|
||||||
msgid "Checked-in Tickets"
|
|
||||||
msgstr "Eingecheckte Tickets"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:69
|
|
||||||
msgid "Valid Tickets"
|
|
||||||
msgstr "Gültige Tickets"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
|
||||||
msgid "Currently inside"
|
|
||||||
msgstr "Derzeit anwesend"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "Ja"
|
|
||||||
|
|
||||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
|
||||||
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
|
||||||
msgid "No"
|
|
||||||
msgstr "Nein"
|
|
||||||
|
|
||||||
#: pretix/static/lightbox/js/lightbox.js:96
|
#: pretix/static/lightbox/js/lightbox.js:96
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr "schließen"
|
msgstr "schließen"
|
||||||
@@ -385,14 +218,14 @@ msgstr ""
|
|||||||
"bitte oder gehen Sie in Ihrem Browser einen Schritt zurück und versuchen es "
|
"bitte oder gehen Sie in Ihrem Browser einen Schritt zurück und versuchen es "
|
||||||
"erneut."
|
"erneut."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
#: pretix/static/pretixbase/js/asynctask.js:135
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:182
|
#: pretix/static/pretixbase/js/asynctask.js:192
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:186
|
#: pretix/static/pretixbase/js/asynctask.js:196
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
#: pretix/static/pretixcontrol/js/ui/mail.js:24
|
||||||
msgid "An error of type {code} occurred."
|
msgid "An error of type {code} occurred."
|
||||||
msgstr "Ein Fehler ist aufgetreten. Fehlercode: {code}"
|
msgstr "Ein Fehler ist aufgetreten. Fehlercode: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:128
|
#: pretix/static/pretixbase/js/asynctask.js:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||||
"{code}"
|
"{code}"
|
||||||
@@ -400,12 +233,12 @@ msgstr ""
|
|||||||
"Wir können den Server aktuell nicht erreichen, versuchen es aber weiter. "
|
"Wir können den Server aktuell nicht erreichen, versuchen es aber weiter. "
|
||||||
"Letzter Fehlercode: {code}"
|
"Letzter Fehlercode: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
#: pretix/static/pretixbase/js/asynctask.js:172
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||||
msgid "The request took too long. Please try again."
|
msgid "The request took too long. Please try again."
|
||||||
msgstr "Diese Anfrage hat zu lange gedauert. Bitte erneut versuchen."
|
msgstr "Diese Anfrage hat zu lange gedauert. Bitte erneut versuchen."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:188
|
#: pretix/static/pretixbase/js/asynctask.js:198
|
||||||
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
#: pretix/static/pretixcontrol/js/ui/mail.js:26
|
||||||
msgid ""
|
msgid ""
|
||||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||||
@@ -413,11 +246,11 @@ msgstr ""
|
|||||||
"Wir können den Server aktuell nicht erreichen. Bitte versuchen Sie es noch "
|
"Wir können den Server aktuell nicht erreichen. Bitte versuchen Sie es noch "
|
||||||
"einmal. Fehlercode: {code}"
|
"einmal. Fehlercode: {code}"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
#: pretix/static/pretixbase/js/asynctask.js:226
|
||||||
msgid "We are processing your request …"
|
msgid "We are processing your request …"
|
||||||
msgstr "Wir verarbeiten Ihre Anfrage …"
|
msgstr "Wir verarbeiten Ihre Anfrage …"
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:219
|
#: pretix/static/pretixbase/js/asynctask.js:229
|
||||||
msgid ""
|
msgid ""
|
||||||
"We are currently sending your request to the server. If this takes longer "
|
"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 "
|
"than one minute, please check your internet connection and then reload this "
|
||||||
@@ -427,11 +260,11 @@ msgstr ""
|
|||||||
"dauert, prüfen Sie bitte Ihre Internetverbindung. Danach können Sie diese "
|
"dauert, prüfen Sie bitte Ihre Internetverbindung. Danach können Sie diese "
|
||||||
"Seite neu laden und es erneut versuchen."
|
"Seite neu laden und es erneut versuchen."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||||
msgid "If this takes longer than a few minutes, please contact us."
|
msgid "If this takes longer than a few minutes, please contact us."
|
||||||
msgstr "Wenn dies länger als einige Minuten dauert, kontaktiere uns bitte."
|
msgstr "Wenn dies länger als einige Minuten dauert, kontaktiere uns bitte."
|
||||||
|
|
||||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||||
msgid "Close message"
|
msgid "Close message"
|
||||||
msgstr "Schließen"
|
msgstr "Schließen"
|
||||||
|
|
||||||
@@ -443,146 +276,6 @@ msgstr "Kopiert!"
|
|||||||
msgid "Press Ctrl-C to copy!"
|
msgid "Press Ctrl-C to copy!"
|
||||||
msgstr "Drücken Sie Strg+C zum Kopieren!"
|
msgstr "Drücken Sie Strg+C zum Kopieren!"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:12
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
|
||||||
msgid "is one of"
|
|
||||||
msgstr "ist eines von"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
|
||||||
msgid "is before"
|
|
||||||
msgstr "ist vor"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:34
|
|
||||||
msgid "is after"
|
|
||||||
msgstr "ist nach"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
|
||||||
msgid "="
|
|
||||||
msgstr "="
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "Produkt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
|
||||||
msgid "Product variation"
|
|
||||||
msgstr "Variante"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
|
||||||
msgid "Gate"
|
|
||||||
msgstr "Station"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
|
||||||
msgid "Current date and time"
|
|
||||||
msgstr "Aktueller Zeitpunkt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
|
||||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
|
||||||
msgstr "Aktueller Tag der Woche (1 = Montag, 7 = Sonntag)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
|
||||||
msgid "Current entry status"
|
|
||||||
msgstr "Aktueller Zutrittsstatus"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
|
||||||
msgid "Number of previous entries"
|
|
||||||
msgstr "Anzahl bisheriger Eintritte"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
|
||||||
msgid "Number of previous entries since midnight"
|
|
||||||
msgstr "Anzahl bisheriger Eintritte seit Mitternacht"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
|
||||||
msgid "Number of previous entries since"
|
|
||||||
msgstr "Anzahl bisheriger Eintritte seit"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
|
||||||
msgid "Number of previous entries before"
|
|
||||||
msgstr "Anzahl bisheriger Eintritte vor"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
|
||||||
msgid "Number of days with a previous entry"
|
|
||||||
msgstr "Anzahl an Tagen mit vorherigem Eintritt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
|
||||||
msgid "Number of days with a previous entry since"
|
|
||||||
msgstr "Anzahl an Tagen mit vorherigem Eintritt seit"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
|
||||||
msgid "Number of days with a previous entry before"
|
|
||||||
msgstr "Anzahl an Tagen mit vorherigem Eintritt vor"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
|
||||||
msgid "Minutes since last entry (-1 on first entry)"
|
|
||||||
msgstr "Minuten seit vorherigem Eintritt (-1 bei erstem Zutritt)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
|
||||||
msgid "Minutes since first entry (-1 on first entry)"
|
|
||||||
msgstr "Minuten seit erstem Eintritt (-1 bei erstem Zutritt)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
|
||||||
msgid "All of the conditions below (AND)"
|
|
||||||
msgstr "Alle der folgenden Bedingungen (UND)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
|
||||||
msgid "At least one of the conditions below (OR)"
|
|
||||||
msgstr "Mindestens eine der folgenden Bedingungen (ODER)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
|
||||||
msgid "Event start"
|
|
||||||
msgstr "Veranstaltungsbeginn"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:185
|
|
||||||
msgid "Event end"
|
|
||||||
msgstr "Veranstaltungsende"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:186
|
|
||||||
msgid "Event admission"
|
|
||||||
msgstr "Einlass"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
|
||||||
msgid "custom date and time"
|
|
||||||
msgstr "Fester Zeitpunkt"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
|
||||||
msgid "custom time"
|
|
||||||
msgstr "Feste Uhrzeit"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
|
||||||
msgid "Tolerance (minutes)"
|
|
||||||
msgstr "Toleranz (Minuten)"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:190
|
|
||||||
msgid "Add condition"
|
|
||||||
msgstr "Bedingung hinzufügen"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:191
|
|
||||||
msgid "minutes"
|
|
||||||
msgstr "Minuten"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
|
||||||
msgid "Duplicate"
|
|
||||||
msgstr "Duplizieren"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "present"
|
|
||||||
msgstr "anwesend"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
|
||||||
msgctxt "entry_status"
|
|
||||||
msgid "absent"
|
|
||||||
msgstr "abwesend"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
|
||||||
msgid "Error: Product not found!"
|
|
||||||
msgstr "Fehler: Produkt nicht gefunden!"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
|
||||||
msgid "Error: Variation not found!"
|
|
||||||
msgstr "Fehler: Variante nicht gefunden!"
|
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||||
msgid "Check-in QR"
|
msgid "Check-in QR"
|
||||||
msgstr "Check-in-QR-Code"
|
msgstr "Check-in-QR-Code"
|
||||||
@@ -724,6 +417,16 @@ msgstr "Sonstige"
|
|||||||
msgid "Count"
|
msgid "Count"
|
||||||
msgstr "Anzahl"
|
msgstr "Anzahl"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "Ja"
|
||||||
|
|
||||||
|
#: pretix/static/pretixcontrol/js/ui/question.js:137
|
||||||
|
#: pretix/static/pretixpresale/js/ui/questions.js:271
|
||||||
|
msgid "No"
|
||||||
|
msgstr "Nein"
|
||||||
|
|
||||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||||
msgid "(one more date)"
|
msgid "(one more date)"
|
||||||
msgid_plural "({num} more dates)"
|
msgid_plural "({num} more dates)"
|
||||||
@@ -1215,6 +918,225 @@ msgstr "November"
|
|||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr "Dezember"
|
msgstr "Dezember"
|
||||||
|
|
||||||
|
#~ msgid "Select a check-in list"
|
||||||
|
#~ msgstr "Wählen Sie eine Check-In Liste"
|
||||||
|
|
||||||
|
#~ msgid "No active check-in lists found."
|
||||||
|
#~ msgstr "Keine aktive Check-In Liste gefunden."
|
||||||
|
|
||||||
|
#~ msgid "Switch check-in list"
|
||||||
|
#~ msgstr "Check-In Liste wechseln"
|
||||||
|
|
||||||
|
#~ msgid "Search results"
|
||||||
|
#~ msgstr "Suchergebnisse"
|
||||||
|
|
||||||
|
#~ msgid "No tickets found"
|
||||||
|
#~ msgstr "Keine Tickets gefunden"
|
||||||
|
|
||||||
|
#~ msgid "Result"
|
||||||
|
#~ msgstr "Ergebnis"
|
||||||
|
|
||||||
|
#~ msgid "This ticket requires special attention"
|
||||||
|
#~ msgstr "Dieses Ticket benötigt besondere Aufmerksamkeit"
|
||||||
|
|
||||||
|
#~ msgid "Switch direction"
|
||||||
|
#~ msgstr "Richtung wechseln"
|
||||||
|
|
||||||
|
#~ msgid "Entry"
|
||||||
|
#~ msgstr "Eingang"
|
||||||
|
|
||||||
|
#~ msgid "Exit"
|
||||||
|
#~ msgstr "Ausgang"
|
||||||
|
|
||||||
|
#~ msgid "Scan a ticket or search and press return…"
|
||||||
|
#~ msgstr "Ticket scannen oder suchen und mit Enter bestätigen…"
|
||||||
|
|
||||||
|
#~ msgid "Load more"
|
||||||
|
#~ msgstr "Mehr laden"
|
||||||
|
|
||||||
|
#~ msgid "Valid"
|
||||||
|
#~ msgstr "Gültig"
|
||||||
|
|
||||||
|
#~ msgid "Unpaid"
|
||||||
|
#~ msgstr "Unbezahlt"
|
||||||
|
|
||||||
|
#~ msgid "Canceled"
|
||||||
|
#~ msgstr "storniert"
|
||||||
|
|
||||||
|
#~ msgid "Confirmed"
|
||||||
|
#~ msgstr "bestätigt"
|
||||||
|
|
||||||
|
#~ msgid "Approval pending"
|
||||||
|
#~ msgstr "Freigabe ausstehend"
|
||||||
|
|
||||||
|
#~ msgid "Redeemed"
|
||||||
|
#~ msgstr "Eingelöst"
|
||||||
|
|
||||||
|
#~ msgid "Cancel"
|
||||||
|
#~ msgstr "Abbrechen"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not paid"
|
||||||
|
#~ msgstr "Ticket nicht bezahlt"
|
||||||
|
|
||||||
|
#~ msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "Dieses Ticket ist noch nicht bezahlt. Möchten Sie dennoch fortfahren?"
|
||||||
|
|
||||||
|
#~ msgid "Additional information required"
|
||||||
|
#~ msgstr "Zusätzliche Informationen benötigt"
|
||||||
|
|
||||||
|
#~ msgid "Valid ticket"
|
||||||
|
#~ msgstr "Gültiges Ticket"
|
||||||
|
|
||||||
|
#~ msgid "Exit recorded"
|
||||||
|
#~ msgstr "Ausgang gespeichert"
|
||||||
|
|
||||||
|
#~ msgid "Ticket already used"
|
||||||
|
#~ msgstr "Ticket bereits eingelöst"
|
||||||
|
|
||||||
|
#~ msgid "Information required"
|
||||||
|
#~ msgstr "Infos benötigt"
|
||||||
|
|
||||||
|
#~ msgid "Unknown ticket"
|
||||||
|
#~ msgstr "Unbekanntes Ticket"
|
||||||
|
|
||||||
|
#~ msgid "Ticket type not allowed here"
|
||||||
|
#~ msgstr "Ticketart hier nicht erlaubt"
|
||||||
|
|
||||||
|
#~ msgid "Entry not allowed"
|
||||||
|
#~ msgstr "Eingang nicht erlaubt"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code revoked/changed"
|
||||||
|
#~ msgstr "Ticket-Code gesperrt/geändert"
|
||||||
|
|
||||||
|
#~ msgid "Ticket blocked"
|
||||||
|
#~ msgstr "Ticket gesperrt"
|
||||||
|
|
||||||
|
#~ msgid "Ticket not valid at this time"
|
||||||
|
#~ msgstr "Ticket aktuell nicht gültig"
|
||||||
|
|
||||||
|
#~ msgid "Order canceled"
|
||||||
|
#~ msgstr "Bestellung storniert"
|
||||||
|
|
||||||
|
#~ msgid "Ticket code is ambiguous on list"
|
||||||
|
#~ msgstr "Ticket-Code ist nicht eindeutig auf der Liste"
|
||||||
|
|
||||||
|
#~ msgid "Order not approved"
|
||||||
|
#~ msgstr "Bestellung nicht freigegeben"
|
||||||
|
|
||||||
|
#~ msgid "Checked-in Tickets"
|
||||||
|
#~ msgstr "Eingecheckte Tickets"
|
||||||
|
|
||||||
|
#~ msgid "Valid Tickets"
|
||||||
|
#~ msgstr "Gültige Tickets"
|
||||||
|
|
||||||
|
#~ msgid "Currently inside"
|
||||||
|
#~ msgstr "Derzeit anwesend"
|
||||||
|
|
||||||
|
#~ msgid "is one of"
|
||||||
|
#~ msgstr "ist eines von"
|
||||||
|
|
||||||
|
#~ msgid "is before"
|
||||||
|
#~ msgstr "ist vor"
|
||||||
|
|
||||||
|
#~ msgid "is after"
|
||||||
|
#~ msgstr "ist nach"
|
||||||
|
|
||||||
|
#~ msgid "="
|
||||||
|
#~ msgstr "="
|
||||||
|
|
||||||
|
#~ msgid "Product"
|
||||||
|
#~ msgstr "Produkt"
|
||||||
|
|
||||||
|
#~ msgid "Product variation"
|
||||||
|
#~ msgstr "Variante"
|
||||||
|
|
||||||
|
#~ msgid "Gate"
|
||||||
|
#~ msgstr "Station"
|
||||||
|
|
||||||
|
#~ msgid "Current date and time"
|
||||||
|
#~ msgstr "Aktueller Zeitpunkt"
|
||||||
|
|
||||||
|
#~ msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||||
|
#~ msgstr "Aktueller Tag der Woche (1 = Montag, 7 = Sonntag)"
|
||||||
|
|
||||||
|
#~ msgid "Current entry status"
|
||||||
|
#~ msgstr "Aktueller Zutrittsstatus"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries"
|
||||||
|
#~ msgstr "Anzahl bisheriger Eintritte"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since midnight"
|
||||||
|
#~ msgstr "Anzahl bisheriger Eintritte seit Mitternacht"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries since"
|
||||||
|
#~ msgstr "Anzahl bisheriger Eintritte seit"
|
||||||
|
|
||||||
|
#~ msgid "Number of previous entries before"
|
||||||
|
#~ msgstr "Anzahl bisheriger Eintritte vor"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry"
|
||||||
|
#~ msgstr "Anzahl an Tagen mit vorherigem Eintritt"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry since"
|
||||||
|
#~ msgstr "Anzahl an Tagen mit vorherigem Eintritt seit"
|
||||||
|
|
||||||
|
#~ msgid "Number of days with a previous entry before"
|
||||||
|
#~ msgstr "Anzahl an Tagen mit vorherigem Eintritt vor"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since last entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuten seit vorherigem Eintritt (-1 bei erstem Zutritt)"
|
||||||
|
|
||||||
|
#~ msgid "Minutes since first entry (-1 on first entry)"
|
||||||
|
#~ msgstr "Minuten seit erstem Eintritt (-1 bei erstem Zutritt)"
|
||||||
|
|
||||||
|
#~ msgid "All of the conditions below (AND)"
|
||||||
|
#~ msgstr "Alle der folgenden Bedingungen (UND)"
|
||||||
|
|
||||||
|
#~ msgid "At least one of the conditions below (OR)"
|
||||||
|
#~ msgstr "Mindestens eine der folgenden Bedingungen (ODER)"
|
||||||
|
|
||||||
|
#~ msgid "Event start"
|
||||||
|
#~ msgstr "Veranstaltungsbeginn"
|
||||||
|
|
||||||
|
#~ msgid "Event end"
|
||||||
|
#~ msgstr "Veranstaltungsende"
|
||||||
|
|
||||||
|
#~ msgid "Event admission"
|
||||||
|
#~ msgstr "Einlass"
|
||||||
|
|
||||||
|
#~ msgid "custom date and time"
|
||||||
|
#~ msgstr "Fester Zeitpunkt"
|
||||||
|
|
||||||
|
#~ msgid "custom time"
|
||||||
|
#~ msgstr "Feste Uhrzeit"
|
||||||
|
|
||||||
|
#~ msgid "Tolerance (minutes)"
|
||||||
|
#~ msgstr "Toleranz (Minuten)"
|
||||||
|
|
||||||
|
#~ msgid "Add condition"
|
||||||
|
#~ msgstr "Bedingung hinzufügen"
|
||||||
|
|
||||||
|
#~ msgid "minutes"
|
||||||
|
#~ msgstr "Minuten"
|
||||||
|
|
||||||
|
#~ msgid "Duplicate"
|
||||||
|
#~ msgstr "Duplizieren"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "present"
|
||||||
|
#~ msgstr "anwesend"
|
||||||
|
|
||||||
|
#~ msgctxt "entry_status"
|
||||||
|
#~ msgid "absent"
|
||||||
|
#~ msgstr "abwesend"
|
||||||
|
|
||||||
|
#~ msgid "Error: Product not found!"
|
||||||
|
#~ msgstr "Fehler: Produkt nicht gefunden!"
|
||||||
|
|
||||||
|
#~ msgid "Error: Variation not found!"
|
||||||
|
#~ msgstr "Fehler: Variante nicht gefunden!"
|
||||||
|
|
||||||
#~ msgid "iDEAL"
|
#~ msgid "iDEAL"
|
||||||
#~ msgstr "iDEAL"
|
#~ msgstr "iDEAL"
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user