Compare commits
3 Commits
fix-widget
...
mf0aes-doc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9150b4b271 | ||
|
|
20c8d8e01d | ||
|
|
f04d7a7274 |
2
.github/dependabot.yml
vendored
@@ -10,9 +10,7 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: increase
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/src/pretix/static/npm_dir"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
8
.github/workflows/build.yml
vendored
@@ -26,19 +26,19 @@ jobs:
|
||||
matrix:
|
||||
python-version: ["3.11"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
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 unzip
|
||||
run: sudo apt update && sudo apt install gettext unzip
|
||||
- name: Install Python dependencies
|
||||
run: pip3 install -U setuptools build pip check-manifest
|
||||
- name: Run check-manifest
|
||||
|
||||
8
.github/workflows/docs.yml
vendored
@@ -25,19 +25,19 @@ jobs:
|
||||
name: Spellcheck
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Install system packages
|
||||
run: sudo apt update && sudo apt install -y enchant-2 hunspell aspell-en
|
||||
run: sudo apt update && sudo apt install enchant-2 hunspell aspell-en
|
||||
- name: Install Dependencies
|
||||
run: pip3 install -Ur requirements.txt
|
||||
working-directory: ./doc
|
||||
|
||||
18
.github/workflows/strings.yml
vendored
@@ -23,21 +23,21 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Check gettext syntax
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Install system packages
|
||||
run: sudo apt update && sudo apt -y install gettext
|
||||
run: sudo apt update && sudo apt install gettext
|
||||
- name: Install Dependencies
|
||||
run: pip3 install uv && uv pip install --system -e ".[dev]"
|
||||
run: pip3 install -e ".[dev]"
|
||||
- name: Compile messages
|
||||
run: python manage.py compilemessages
|
||||
working-directory: ./src
|
||||
@@ -48,12 +48,12 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Spellcheck
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
- name: Install system packages
|
||||
run: sudo apt update && sudo apt install enchant-2 hunspell hunspell-de-de aspell-en aspell-de
|
||||
- name: Install Dependencies
|
||||
run: pip3 install uv && uv pip install --system -e ".[dev]"
|
||||
run: pip3 install -e ".[dev]"
|
||||
- name: Spellcheck translations
|
||||
run: potypo
|
||||
working-directory: ./src
|
||||
|
||||
20
.github/workflows/style.yml
vendored
@@ -23,19 +23,19 @@ jobs:
|
||||
name: isort
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Install Dependencies
|
||||
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
|
||||
run: pip3 install -e ".[dev]" psycopg2-binary
|
||||
- name: Run isort
|
||||
run: isort -c .
|
||||
working-directory: ./src
|
||||
@@ -43,19 +43,19 @@ jobs:
|
||||
name: flake8
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Install Dependencies
|
||||
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
|
||||
run: pip3 install -e ".[dev]" psycopg2-binary
|
||||
- name: Run flake8
|
||||
run: flake8 .
|
||||
working-directory: ./src
|
||||
@@ -63,9 +63,9 @@ jobs:
|
||||
name: licenseheaders
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.11
|
||||
- name: Install Dependencies
|
||||
|
||||
41
.github/workflows/tests.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
- 'src/pretix/locale/**'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
@@ -30,35 +31,29 @@ jobs:
|
||||
python-version: "3.9"
|
||||
- database: sqlite
|
||||
python-version: "3.10"
|
||||
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
|
||||
- uses: actions/checkout@v2
|
||||
- uses: harmon758/postgresql-action@v1
|
||||
with:
|
||||
postgresql version: '11'
|
||||
postgresql db: 'pretix'
|
||||
postgresql user: 'postgres'
|
||||
postgresql password: 'postgres'
|
||||
if: matrix.database == 'postgres'
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v1
|
||||
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
|
||||
run: sudo apt update && sudo apt install gettext
|
||||
- name: Install Python dependencies
|
||||
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
|
||||
run: pip3 install --ignore-requires-python -e ".[dev]" psycopg2-binary # We ignore that flake8 needs newer python as we don't run flake8 during tests
|
||||
- name: Run checks
|
||||
run: python manage.py check
|
||||
working-directory: ./src
|
||||
@@ -70,15 +65,11 @@ jobs:
|
||||
run: make all compress
|
||||
- name: Run tests
|
||||
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
|
||||
- name: Run concurrency tests
|
||||
working-directory: ./src
|
||||
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test tests/concurrency_tests/ --reuse-db
|
||||
if: matrix.database == 'postgres'
|
||||
run: PRETIX_CONFIG_FILE=tests/travis_${{ matrix.database }}.cfg py.test -n 3 -p no:sugar --cov=./ --cov-report=xml --reruns 3 tests --maxfail=100
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
file: src/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: false
|
||||
fail_ci_if_error: true
|
||||
if: matrix.database == 'postgres' && matrix.python-version == '3.11'
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
before_script:
|
||||
tests:
|
||||
image:
|
||||
name: pretix/ci-image
|
||||
stage: test
|
||||
before_script:
|
||||
- pip install -U pip uv
|
||||
- uv pip install --system -U wheel setuptools
|
||||
script:
|
||||
- uv pip install --system -e ".[dev]"
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache pip3 install -e ".[dev]"
|
||||
- cd src
|
||||
- python manage.py check
|
||||
- make all compress
|
||||
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test -n 3 tests --maxfail=100
|
||||
- py.test --reruns 3 -n 3 tests
|
||||
tags:
|
||||
- python3
|
||||
except:
|
||||
- pypi
|
||||
pypi:
|
||||
stage: release
|
||||
image:
|
||||
name: pretix/ci-image
|
||||
before_script:
|
||||
- cat $PYPIRC > ~/.pypirc
|
||||
- pip install -U pip uv
|
||||
- uv pip install --system -U wheel setuptools twine build pretix-plugin-build check-manifest
|
||||
script:
|
||||
- uv pip install --system -e ".[dev]"
|
||||
- cp /keys/.pypirc ~/.pypirc
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools check-manifest twine
|
||||
- XDG_CACHE_HOME=/cache pip3 install -e ".[dev]"
|
||||
- python setup.py sdist
|
||||
- uv pip install --system dist/pretix-*.tar.gz
|
||||
- pip install dist/pretix-*.tar.gz
|
||||
- python -m pretix migrate
|
||||
- python -m pretix check
|
||||
- cd src
|
||||
@@ -34,12 +33,13 @@ pypi:
|
||||
- python -m build
|
||||
- twine check dist/*
|
||||
- twine upload dist/*
|
||||
tags:
|
||||
- python3
|
||||
only:
|
||||
- pypi
|
||||
artifacts:
|
||||
paths:
|
||||
- src/dist/
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
17
|
||||
24
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM python:3.11-bookworm
|
||||
FROM python:3.11-bullseye
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
@@ -20,20 +20,20 @@ RUN apt-get update && \
|
||||
supervisor \
|
||||
libmaxminddb0 \
|
||||
libmaxminddb-dev \
|
||||
zlib1g-dev \
|
||||
nodejs \
|
||||
npm && \
|
||||
zlib1g-dev && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8 && \
|
||||
dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8 && \
|
||||
mkdir /etc/pretix && \
|
||||
mkdir /data && \
|
||||
useradd -ms /bin/bash -d /pretix -u 15371 pretixuser && \
|
||||
echo 'pretixuser ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers && \
|
||||
mkdir /static && \
|
||||
mkdir /etc/supervisord
|
||||
mkdir /etc/supervisord && \
|
||||
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - && \
|
||||
apt-get install -y nodejs
|
||||
|
||||
|
||||
ENV LC_ALL=C.UTF-8 \
|
||||
@@ -63,10 +63,10 @@ RUN pip3 install -U \
|
||||
RUN chmod +x /usr/local/bin/pretix && \
|
||||
rm /etc/nginx/sites-enabled/default && \
|
||||
cd /pretix/src && \
|
||||
rm -f pretix.cfg && \
|
||||
mkdir -p data && \
|
||||
chown -R pretixuser:pretixuser /pretix /data data && \
|
||||
sudo -u pretixuser make production
|
||||
rm -f pretix.cfg && \
|
||||
mkdir -p data && \
|
||||
chown -R pretixuser:pretixuser /pretix /data data && \
|
||||
sudo -u pretixuser make production
|
||||
|
||||
USER pretixuser
|
||||
VOLUME ["/etc/pretix", "/data"]
|
||||
|
||||
@@ -10,8 +10,6 @@ recursive-include src/pretix/helpers/locale *
|
||||
recursive-include src/pretix/base/templates *
|
||||
recursive-include src/pretix/control/templates *
|
||||
recursive-include src/pretix/presale/templates *
|
||||
recursive-include src/pretix/plugins/autocheckin/templates *
|
||||
recursive-include src/pretix/plugins/autocheckin/static *
|
||||
recursive-include src/pretix/plugins/banktransfer/templates *
|
||||
recursive-include src/pretix/plugins/banktransfer/static *
|
||||
recursive-include src/pretix/plugins/manualpayment/templates *
|
||||
|
||||
@@ -60,14 +60,6 @@ http {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location /static/staticfiles.json {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location /static/CACHE/manifest.json {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location /static/ {
|
||||
alias /pretix/src/pretix/static.dist/;
|
||||
access_log off;
|
||||
|
||||
@@ -5,7 +5,7 @@ export DATA_DIR=/data/
|
||||
export HOME=/pretix
|
||||
|
||||
AUTOMIGRATE=${AUTOMIGRATE:-yes}
|
||||
NUM_WORKERS_DEFAULT=$((2 * $(nproc)))
|
||||
NUM_WORKERS_DEFAULT=$((2 * $(nproc --all)))
|
||||
export NUM_WORKERS=${NUM_WORKERS:-$NUM_WORKERS_DEFAULT}
|
||||
|
||||
if [ ! -d /data/logs ]; then
|
||||
@@ -47,7 +47,7 @@ if [ "$1" == "taskworker" ]; then
|
||||
fi
|
||||
|
||||
if [ "$1" == "upgrade" ]; then
|
||||
exec python3 -m pretix updateassets
|
||||
exec python3 -m pretix updatestyles
|
||||
fi
|
||||
|
||||
exec python3 -m pretix "$@"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from pretix.settings import *
|
||||
|
||||
LOGGING['handlers']['mail_admins']['include_html'] = True
|
||||
STORAGES["staticfiles"]["BACKEND"] = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||
|
||||
71
doc/_templates/index.html
vendored
@@ -1,16 +1,43 @@
|
||||
{% extends "layout.html" %}
|
||||
{% set title = 'Overview' %}
|
||||
{% block body %}
|
||||
<h1>Welcome to our developer documentation!</h1>
|
||||
<h1>Welcome to pretix' documentation!</h1>
|
||||
<p>
|
||||
We work hard to make this website contain all information that you need to work with our API or source code.
|
||||
Of course, this documentation will never be perfect or complete, but if there is anything unclear
|
||||
We work hard to make this website contain all information that you need to use, run, understand, and improve
|
||||
pretix. Of course, this documentation will never be perfect or complete, but if there is anything unclear
|
||||
or anything specific that you miss here, that's a bug and we'd be happy if you'd
|
||||
<a href="https://github.com/pretix/pretix/issues/new">let us know</a>.
|
||||
</p>
|
||||
|
||||
<h2>What you can find here</h2>
|
||||
<h2>Documentation structure</h2>
|
||||
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="user/index.html">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="user/index.html">
|
||||
<strong>User Guide</strong>
|
||||
</a>
|
||||
<p>Go here to find information on how to configure and use pretix as an event organizer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="admin/index.html">
|
||||
<span class="fa fa-server fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="admin/index.html">
|
||||
<strong>Administrator docs</strong>
|
||||
</a>
|
||||
<p>Find out how to install pretix on your own server and how to maintain an installation of pretix.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="api/index.html">
|
||||
@@ -42,33 +69,30 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
|
||||
<h2>Other sources of documentation</h2>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://docs.pretix.eu" target="_blank">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
<a href="plugins/index.html">
|
||||
<span class="fa fa-puzzle-piece fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://docs.pretix.eu" target="_blank">
|
||||
<strong>User docs</strong>
|
||||
<a href="plugins/index.html">
|
||||
<strong>Plugin docs</strong>
|
||||
</a>
|
||||
<p>Go here to find information on how to configure and use pretix as an event organizer.</p>
|
||||
<p>Documentation and details on plugins that ship with pretix or are officially supported.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://docs.pretix.eu/self-hosting/">
|
||||
<span class="fa fa-server fa-fw"></span>
|
||||
<a href="contents.html">
|
||||
<span class="fa fa-list fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://docs.pretix.eu/self-hosting/">
|
||||
<strong>Administrator docs</strong>
|
||||
<a href="contents.html">
|
||||
<strong>Table of contents</strong>
|
||||
</a>
|
||||
<p>Find out how to install pretix on your own server and how to maintain an installation of pretix.</p>
|
||||
<p>Detailled overview of everything contained in this documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
@@ -118,6 +142,19 @@
|
||||
general news on pretix as a project.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<span class="fa fa-twitter fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<strong>Twitter</strong>
|
||||
</a>
|
||||
<p>Keep in touch and stay up to date by following our project account on Twitter.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
{% endblock %}
|
||||
1
doc/_themes/pretix_theme/layout.html
vendored
@@ -115,7 +115,6 @@
|
||||
{%- if logo or logo_url %}
|
||||
<img src="{{ _logo_url }}" class="logo" alt="{{ _('Logo') }}"/>
|
||||
{%- endif %}
|
||||
Developer Documentation
|
||||
</a>
|
||||
|
||||
{% include "searchbox.html" %}
|
||||
|
||||
@@ -5183,7 +5183,7 @@ div[class^='highlight'] pre {
|
||||
|
||||
.wy-side-nav-search > a img.logo, .wy-side-nav-search .wy-dropdown > a img.logo {
|
||||
display: block;
|
||||
margin: 0 auto 10px;
|
||||
margin: 0 auto;
|
||||
height: 50px;
|
||||
width: auto;
|
||||
border-radius: 0;
|
||||
|
||||
521
doc/admin/config.rst
Normal file
@@ -0,0 +1,521 @@
|
||||
.. highlight:: ini
|
||||
|
||||
.. _`config`:
|
||||
|
||||
.. spelling:word-list:: Galera
|
||||
|
||||
Configuration file
|
||||
==================
|
||||
|
||||
Pretix reads its configuration from a configuration file. It tries to find this file
|
||||
at the following locations. It will try to read the file from the specified paths in
|
||||
the following order. The file that is found *last* will override the settings from
|
||||
the files found before.
|
||||
|
||||
1. ``PRETIX_CONFIG_FILE`` environment variable
|
||||
2. ``/etc/pretix/pretix.cfg``
|
||||
3. ``~/.pretix.cfg``
|
||||
4. ``pretix.cfg`` in the current working directory
|
||||
|
||||
The file is expected to be in the INI format as specified in the `Python documentation`_.
|
||||
|
||||
The config file may contain the following sections (all settings are optional and have
|
||||
default values). We suggest that you start from the examples given in one of the
|
||||
installation tutorials.
|
||||
|
||||
.. note::
|
||||
|
||||
The configuration file is the recommended way to configure pretix. However, you can
|
||||
also set them through environment variables. In this case, the syntax is
|
||||
``PRETIX_SECTION_CONFIG``. For example, to configure the setting ``password_reset``
|
||||
from the ``[pretix]`` section, set ``PRETIX_PRETIX_PASSWORD_RESET=off`` in your
|
||||
environment.
|
||||
|
||||
pretix settings
|
||||
---------------
|
||||
|
||||
Example::
|
||||
|
||||
[pretix]
|
||||
instance_name=pretix.de
|
||||
url=http://localhost
|
||||
currency=EUR
|
||||
datadir=/data
|
||||
plugins_default=pretix.plugins.sendmail,pretix.plugins.statistics
|
||||
cookie_domain=.pretix.de
|
||||
|
||||
``instance_name``
|
||||
The name of this installation. Default: ``pretix.de``
|
||||
|
||||
``url``
|
||||
The installation's full URL, without a trailing slash.
|
||||
|
||||
``currency``
|
||||
The default currency as a three-letter code. Defaults to ``EUR``.
|
||||
|
||||
``datadir``
|
||||
The local path to a data directory that will be used for storing user uploads and similar
|
||||
data. Defaults to the value of the environment variable ``DATA_DIR`` or ``data``.
|
||||
|
||||
``plugins_default``
|
||||
A comma-separated list of plugins that are enabled by default for all new events.
|
||||
Defaults to ``pretix.plugins.sendmail,pretix.plugins.statistics``.
|
||||
|
||||
``plugins_exclude``
|
||||
A comma-separated list of plugins that are not available even though they are installed.
|
||||
Defaults to an empty string.
|
||||
|
||||
``plugins_show_meta``
|
||||
Whether to show authors and versions of plugins, defaults to ``on``.
|
||||
|
||||
``auth_backends``
|
||||
A comma-separated list of available auth backends. Defaults to ``pretix.base.auth.NativeAuthBackend``.
|
||||
|
||||
``cookie_domain``
|
||||
The cookie domain to be set. Defaults to ``None``.
|
||||
|
||||
``registration``
|
||||
Enables or disables the registration of new admin users. Defaults to ``on``.
|
||||
|
||||
``password_reset``
|
||||
Enables or disables password reset. Defaults to ``on``.
|
||||
|
||||
``long_sessions``
|
||||
Enables or disables the "keep me logged in" button. Defaults to ``on``.
|
||||
|
||||
``ecb_rates``
|
||||
By default, pretix periodically downloads currency rates from the European Central Bank as well as other authorities
|
||||
that are used to print tax amounts in the customer currency on invoices for some currencies. Set to ``off`` to
|
||||
disable this feature. Defaults to ``on``.
|
||||
|
||||
``audit_comments``
|
||||
Enables or disables nagging staff users for leaving comments on their sessions for auditability.
|
||||
Defaults to ``off``.
|
||||
|
||||
``obligatory_2fa``
|
||||
Enables or disables obligatory usage of Two-Factor Authentication for users of the pretix backend.
|
||||
Defaults to ``False``
|
||||
|
||||
``trust_x_forwarded_for``
|
||||
Specifies whether the ``X-Forwarded-For`` header can be trusted. Only set to ``on`` if you have a reverse
|
||||
proxy that actively removes and re-adds the header to make sure the correct client IP is the first value.
|
||||
Defaults to ``off``.
|
||||
|
||||
``trust_x_forwarded_proto``
|
||||
Specifies whether the ``X-Forwarded-Proto`` header can be trusted. Only set to ``on`` if you have a reverse
|
||||
proxy that actively removes and re-adds the header to make sure the correct value is set.
|
||||
Defaults to ``off``.
|
||||
|
||||
``trust_x_forwarded_host``
|
||||
Specifies whether the ``X-Forwarded-Host`` header can be trusted. Only set to ``on`` if you have a reverse
|
||||
proxy that actively removes and re-adds the header to make sure the correct value is set.
|
||||
Defaults to ``off``.
|
||||
|
||||
``csp_log``
|
||||
Log violations of the Content Security Policy (CSP). Defaults to ``on``.
|
||||
|
||||
``csp_additional_header``
|
||||
Specifies a CSP header that will be **merged** with pretix's default header. For example, if you set this
|
||||
to ``script-src https://mycdn.com``, pretix will add ``https://mycdn.com`` as an **additional** allowed source
|
||||
to all CSP headers. Empty by default.
|
||||
|
||||
``loglevel``
|
||||
Set console and file log level (``DEBUG``, ``INFO``, ``WARNING``, ``ERROR`` or ``CRITICAL``). Defaults to ``INFO``.
|
||||
|
||||
``request_id_header``
|
||||
Specifies the name of a header that should be used for logging request IDs. Off by default.
|
||||
|
||||
Locale settings
|
||||
---------------
|
||||
|
||||
Example::
|
||||
|
||||
[locale]
|
||||
default=de
|
||||
timezone=Europe/Berlin
|
||||
|
||||
``default``
|
||||
The system's default locale. Default: ``en``
|
||||
|
||||
``timezone``
|
||||
The system's default timezone as a ``pytz`` name. Default: ``UTC``
|
||||
|
||||
Database settings
|
||||
-----------------
|
||||
|
||||
Example::
|
||||
|
||||
[database]
|
||||
backend=postgresql
|
||||
name=pretix
|
||||
user=pretix
|
||||
password=abcd
|
||||
host=localhost
|
||||
port=3306
|
||||
sslmode=require
|
||||
sslrootcert=/etc/pretix/postgresql-ca.crt
|
||||
sslcert=/etc/pretix/postgresql-client-crt.crt
|
||||
sslkey=/etc/pretix/postgresql-client-key.key
|
||||
|
||||
``backend``
|
||||
One of ``sqlite3`` and ``postgresql``.
|
||||
Default: ``sqlite3``.
|
||||
|
||||
``name``
|
||||
The database's name. Default: ``db.sqlite3``.
|
||||
|
||||
``user``, ``password``, ``host``, ``port``
|
||||
Connection details for the database connection. Empty by default.
|
||||
|
||||
``sslmode``, ``sslrootcert``
|
||||
Connection TLS details for the PostgreSQL database connection. Possible values of ``sslmode`` are ``disable``, ``allow``, ``prefer``, ``require``, ``verify-ca``, and ``verify-full``. ``sslrootcert`` should be the accessible path of the ca certificate. Both values are empty by default.
|
||||
|
||||
``sslcert``, ``sslkey``
|
||||
Connection mTLS details for the PostgreSQL database connection. It's also necessary to specify ``sslmode`` and ``sslrootcert`` parameters, please check the correct values from the TLS part. ``sslcert`` should be the accessible path of the client certificate. ``sslkey`` should be the accessible path of the client key. All values are empty by default.
|
||||
.. _`config-replica`:
|
||||
|
||||
Database replica settings
|
||||
-------------------------
|
||||
|
||||
If you use a replicated database setup, pretix expects that the default database connection always points to the primary database node.
|
||||
Routing read queries to a replica on database layer is **strongly** discouraged since this can lead to inaccurate such as more tickets
|
||||
being sold than are actually available.
|
||||
|
||||
However, pretix can still make use of a database replica to keep some expensive queries with that can tolerate some latency from your
|
||||
primary database, such as backend search queries. The ``replica`` configuration section can have the same settings as the ``database``
|
||||
section (except for the ``backend`` setting) and will default back to the ``database`` settings for all values that are not given. This
|
||||
way, you just need to specify the settings that are different for the replica.
|
||||
|
||||
Example::
|
||||
|
||||
[replica]
|
||||
host=192.168.0.2
|
||||
|
||||
.. _`config-urls`:
|
||||
|
||||
URLs
|
||||
----
|
||||
|
||||
Example::
|
||||
|
||||
[urls]
|
||||
media=/media/
|
||||
static=/static/
|
||||
|
||||
``media``
|
||||
The URL to be used to serve user-uploaded content. You should not need to modify
|
||||
this. Default: ``/media/``
|
||||
|
||||
``static``
|
||||
The URL to be used to serve static files. You should not need to modify
|
||||
this. Default: ``/static/``
|
||||
|
||||
.. _`mail-settings`:
|
||||
|
||||
Email
|
||||
-----
|
||||
|
||||
Example::
|
||||
|
||||
[mail]
|
||||
from=hello@localhost
|
||||
host=127.0.0.71
|
||||
user=pretix
|
||||
password=foobar
|
||||
port=1025
|
||||
tls=on
|
||||
ssl=off
|
||||
|
||||
``host``, ``port``
|
||||
The SMTP Host to connect to. Defaults to ``localhost`` and ``25``.
|
||||
|
||||
``user``, ``password``
|
||||
The SMTP user data to use for the connection. Empty by default.
|
||||
|
||||
``tls``, ``ssl``
|
||||
Use STARTTLS or SSL for the SMTP connection. Off by default.
|
||||
|
||||
``from``
|
||||
The email address to set as ``From`` header in outgoing emails by the system.
|
||||
Default: ``pretix@localhost``
|
||||
|
||||
``from_notifications``
|
||||
The email address to set as ``From`` header in admin notification emails by the system.
|
||||
Defaults to the value of ``from``.
|
||||
|
||||
``from_organizers``
|
||||
The email address to set as ``From`` header in outgoing emails by the system sent on behalf of organizers.
|
||||
Defaults to the value of ``from``.
|
||||
|
||||
``custom_sender_verification_required``
|
||||
If this is on (the default), organizers need to verify email addresses they want to use as senders in their event.
|
||||
|
||||
``custom_sender_spf_string``
|
||||
If this is set to a valid SPF string, pretix will show a warning if organizers use a sender address from a domain
|
||||
that does not include this value.
|
||||
|
||||
``custom_smtp_allow_private_networks``
|
||||
If this is off (the default), custom SMTP servers cannot be private network addresses.
|
||||
|
||||
``admins``
|
||||
Comma-separated list of email addresses that should receive a report about every error code 500 thrown by pretix.
|
||||
|
||||
.. _`django-settings`:
|
||||
|
||||
Django settings
|
||||
---------------
|
||||
|
||||
Example::
|
||||
|
||||
[django]
|
||||
secret=j1kjps5a5&4ilpn912s7a1!e2h!duz^i3&idu@_907s$wrz@x-
|
||||
debug=off
|
||||
|
||||
``secret``
|
||||
The secret to be used by Django for signing and verification purposes. If this
|
||||
setting is not provided, pretix will generate a random secret on the first start
|
||||
and will store it in the filesystem for later usage.
|
||||
|
||||
``debug``
|
||||
Whether or not to run in debug mode. Default is ``False``.
|
||||
|
||||
.. WARNING:: Never set this to ``True`` in production!
|
||||
|
||||
``profile``
|
||||
Enable code profiling for a random subset of requests. Disabled by default, see
|
||||
:ref:`perf-monitoring` for details.
|
||||
|
||||
.. _`metrics-settings`:
|
||||
|
||||
Metrics
|
||||
-------
|
||||
|
||||
If you want to fetch internally collected prometheus-style metrics you need to configure the credentials for the
|
||||
metrics endpoint and enable it::
|
||||
|
||||
[metrics]
|
||||
enabled=true
|
||||
user=your_user
|
||||
passphrase=mysupersecretpassphrase
|
||||
|
||||
Currently, metrics-collection requires a redis server to be available.
|
||||
|
||||
|
||||
Memcached
|
||||
---------
|
||||
|
||||
You can use an existing memcached server as pretix's caching backend::
|
||||
|
||||
[memcached]
|
||||
location=127.0.0.1:11211
|
||||
|
||||
``location``
|
||||
The location of memcached, either a host:port combination or a socket file.
|
||||
|
||||
If no memcached is configured, pretix will use redis for caching. If neither is configured, pretix will not use any caching.
|
||||
|
||||
.. note:: If you use memcached and you deploy pretix across multiple servers, you should use *one*
|
||||
shared memcached instance, not multiple ones, because cache invalidations would not be
|
||||
propagated otherwise.
|
||||
|
||||
Redis
|
||||
-----
|
||||
|
||||
If a redis server is configured, pretix can use it for locking, caching and session storage
|
||||
to speed up various operations::
|
||||
|
||||
[redis]
|
||||
location=redis://127.0.0.1:6379/1
|
||||
sessions=false
|
||||
sentinels=[
|
||||
["sentinel_host_1", 26379],
|
||||
["sentinel_host_2", 26379],
|
||||
["sentinel_host_3", 26379]
|
||||
]
|
||||
password=password
|
||||
ssl_cert_reqs=required
|
||||
ssl_ca_certs=/etc/pretix/redis-ca.pem
|
||||
ssl_keyfile=/etc/pretix/redis-client-crt.pem
|
||||
ssl_certfile=/etc/pretix/redis-client-key.key
|
||||
|
||||
``location``
|
||||
The location of redis, as a URL of the form ``redis://[:password]@localhost:6379/0``
|
||||
or ``unix://[:password]@/path/to/socket.sock?db=0``
|
||||
|
||||
``session``
|
||||
When this is set to ``True``, redis will be used as the session storage.
|
||||
|
||||
``sentinels``
|
||||
Configures redis sentinels to use.
|
||||
If you don't want to use redis sentinels, you should omit this option.
|
||||
If this is set, redis via sentinels will be used instead of plain redis.
|
||||
In this case the location should be of the form ``redis://my_master/0``.
|
||||
The ``sentinels`` variable should be a json serialized list of sentinels,
|
||||
each being a list with the two elements hostname and port.
|
||||
You cannot provide a password within the location when using sentinels.
|
||||
Note that the configuration format requires you to either place the entire
|
||||
value on one line or make sure all values are indented by at least one space.
|
||||
|
||||
``password``
|
||||
If your redis setup doesn't require a password or you already specified it in the location you can omit this option.
|
||||
If this is set it will be passed to redis as the connection option PASSWORD.
|
||||
|
||||
``ssl_cert_reqs``
|
||||
If this is set it will be passed to redis as the connection option ``SSL_CERT_REQS``.
|
||||
Possible values are ``none``, ``optional``, and ``required``.
|
||||
|
||||
``ssl_ca_certs``
|
||||
If your redis setup doesn't require TLS you can omit this option.
|
||||
If this is set it will be passed to redis as the connection option ``SSL_CA_CERTS``. Possible value is the ca path.
|
||||
|
||||
``ssl_keyfile``
|
||||
If your redis setup doesn't require mTLS you can omit this option.
|
||||
If this is set it will be passed to redis as the connection option ``SSL_KEYFILE``. Possible value is the keyfile path.
|
||||
|
||||
``ssl_certfile``
|
||||
If your redis setup doesn't require mTLS you can omit this option.
|
||||
If this is set it will be passed to redis as the connection option ``SSL_CERTFILE``. Possible value is the certfile path.
|
||||
|
||||
If redis is not configured, pretix will store sessions and locks in the database. If memcached
|
||||
is configured, memcached will be used for caching instead of redis.
|
||||
|
||||
Translations
|
||||
------------
|
||||
|
||||
pretix comes with a number of translations. All languages are enabled by default. If you want to limit
|
||||
the languages available in your installation, you can enable a set of languages like this::
|
||||
|
||||
[languages]
|
||||
enabled=en,de
|
||||
|
||||
Some of the languages them are marked as "incubating", which means
|
||||
they can usually only be selected in development mode. If you want to use them nevertheless, you
|
||||
can activate them like this::
|
||||
|
||||
[languages]
|
||||
allow_incubating=pt-br,da
|
||||
|
||||
You can also tell pretix about additional paths where it will search for translations::
|
||||
|
||||
[languages]
|
||||
path=/path/to/my/translations
|
||||
|
||||
For a given language (e.g. ``pt-br``), pretix will then look in the
|
||||
specific sub-folder, e.g. ``/path/to/my/translations/pt_BR/LC_MESSAGES/django.po``.
|
||||
|
||||
Celery task queue
|
||||
-----------------
|
||||
|
||||
For processing long-running tasks asynchronously, pretix requires the celery task queue.
|
||||
For communication between the web server and the task workers in both direction, a messaging
|
||||
queue and a result backend is needed. You can use a redis database for both directions, or
|
||||
an AMQP server (e.g. RabbitMQ) as a broker and redis or your database as a result backend::
|
||||
|
||||
[celery]
|
||||
broker=amqp://guest:guest@localhost:5672//
|
||||
backend=redis://localhost/0
|
||||
broker_transport_options="{}"
|
||||
backend_transport_options="{}"
|
||||
|
||||
RabbitMQ might be the better choice if you have a complex, multi-server, high-performance setup,
|
||||
but as you already should have a redis instance ready for session and lock storage, we recommend
|
||||
redis for convenience. See the `Celery documentation`_ for more details.
|
||||
|
||||
The two ``transport_options`` entries can be omitted in most cases.
|
||||
If they are present they need to be a valid JSON dictionary.
|
||||
For possible entries in that dictionary see the `Celery documentation`_.
|
||||
|
||||
It is possible the use Redis with TLS/mTLS for the broker or the backend. To do so, it is necessary to specify the TLS identifier ``rediss``, the ssl mode ``ssl_cert_reqs`` and optionally specify the CA (TLS) ``ssl_ca_certs``, cert ``ssl_certfile`` and key ``ssl_keyfile`` (mTLS) path as encoded string. the following uri describes the format and possible parameters ``rediss://0.0.0.0:6379/1?ssl_cert_reqs=required&ssl_ca_certs=%2Fetc%2Fpretix%2Fredis-ca.pem&ssl_certfile=%2Fetc%2Fpretix%2Fredis-client-crt.pem&ssl_keyfile=%2Fetc%2Fpretix%2Fredis-client-key.key``
|
||||
|
||||
To use redis with sentinels set the broker or backend to ``sentinel://sentinel_host_1:26379;sentinel_host_2:26379/0``
|
||||
and the respective transport_options to ``{"master_name":"mymaster"}``.
|
||||
If your redis instances behind the sentinel have a password use ``sentinel://:my_password@sentinel_host_1:26379;sentinel_host_2:26379/0``.
|
||||
If your redis sentinels themselves have a password set the transport_options to ``{"master_name":"mymaster","sentinel_kwargs":{"password":"my_password"}}``.
|
||||
|
||||
Sentry
|
||||
------
|
||||
|
||||
pretix has native support for sentry, a tool that you can use to track errors in the
|
||||
application. If you want to use sentry, you need to set a DSN in the configuration file::
|
||||
|
||||
[sentry]
|
||||
dsn=https://<key>:<secret>@sentry.io/<project>
|
||||
traces_sample_rate=0.5
|
||||
traces_sample_token=xyz
|
||||
|
||||
``dsn``
|
||||
You will be given this value by your sentry installation.
|
||||
|
||||
``traces_sample_rate``
|
||||
Sample rate for performance monitoring.
|
||||
|
||||
``traces_sample_token``
|
||||
If this token is found in a query string, a trace will always be sampled.
|
||||
|
||||
|
||||
Caching
|
||||
-------
|
||||
|
||||
You can adjust some caching settings to control how much storage pretix uses::
|
||||
|
||||
[cache]
|
||||
tickets=48 ; Number of hours tickets (PDF, passbook, …) are cached
|
||||
|
||||
|
||||
Secret length
|
||||
-------------
|
||||
|
||||
If you are really paranoid, you can increase the length of random strings pretix uses in
|
||||
various places like order codes, secrets in the ticket QR codes, etc. Example::
|
||||
|
||||
[entropy]
|
||||
; Order code needs to be < 16 characters, default is 5
|
||||
order_code=5
|
||||
; Ticket secret needs to be < 64 characters, default is 32
|
||||
ticket_secret=32
|
||||
; Voucher code needs to be < 255 characters, default is 16
|
||||
voucher_code=16
|
||||
|
||||
External tools
|
||||
--------------
|
||||
|
||||
pretix can make use of some external tools if they are installed. Currently, they are all optional. Example::
|
||||
|
||||
[tools]
|
||||
pdftk=/usr/bin/pdftk
|
||||
|
||||
.. _Python documentation: https://docs.python.org/3/library/configparser.html?highlight=configparser#supported-ini-file-structure
|
||||
.. _Celery documentation: http://docs.celeryproject.org/en/latest/userguide/configuration.html
|
||||
|
||||
Maximum upload file sizes
|
||||
-------------------------
|
||||
|
||||
You can configure the maximum file size for uploading various files::
|
||||
|
||||
[pretix_file_upload]
|
||||
; Max upload size for images in MiB, defaults to 10 MiB
|
||||
max_size_image = 12
|
||||
; Max upload size for favicons in MiB, defaults to 1 MiB
|
||||
max_size_favicon = 2
|
||||
; Max upload size for email attachments of manually sent emails in MiB, defaults to 10 MiB
|
||||
max_size_email_attachment = 15
|
||||
; Max upload size for email attachments of automatically sent emails in MiB, defaults to 1 MiB
|
||||
max_size_email_auto_attachment = 2
|
||||
; Max upload size for other files in MiB, defaults to 10 MiB
|
||||
; This includes all file upload type order questions
|
||||
max_size_other = 100
|
||||
|
||||
|
||||
GeoIP
|
||||
-----
|
||||
|
||||
pretix can optionally make use of a GeoIP database for some features. It needs a file in ``mmdb`` format, for example
|
||||
`GeoLite2`_ or `GeoAcumen`_::
|
||||
|
||||
[geoip]
|
||||
path=/var/geoipdata/
|
||||
filename_country=GeoLite2-Country.mmdb
|
||||
|
||||
|
||||
.. _GeoAcumen: https://github.com/geoacumen/geoacumen-country
|
||||
.. _GeoLite2: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
|
||||
40
doc/admin/errors.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
.. _`admin-errors`:
|
||||
|
||||
Dealing with errors
|
||||
===================
|
||||
|
||||
If you encounter an error in pretix, please follow the following steps to debug it:
|
||||
|
||||
* If the error message is shown on a **white page** and the last line of the error includes "nginx", the error is not with pretix
|
||||
directly but with your nginx webserver. This might mean that pretix is not running, but it could also be something else.
|
||||
Please first check your nginx error log. The default location is ``/var/log/nginx/error.log``.
|
||||
|
||||
* If it turns out pretix is not running, check the output of ``docker logs pretix`` for a docker installation and
|
||||
``journalctl -u pretix-web.service`` for a manual installation.
|
||||
|
||||
* If the error message is an "**Internal Server Error**" in purple pretix design, please check pretix' log file which by default is at
|
||||
``/var/pretix-data/logs/pretix.log`` if you installed with docker and ``/var/pretix/data/logs/pretix.log`` otherwise. If you don't
|
||||
know how to interpret it, open a discussion on GitHub with the relevant parts of the log file.
|
||||
|
||||
* If the error message includes ``/usr/bin/env: ‘node’: No such file or directory``, you forgot to install ``node.js``
|
||||
|
||||
* If the error message includes ``OfflineGenerationError``, you might have forgot to run the ``rebuild`` step after a pretix update
|
||||
or plugin installation.
|
||||
|
||||
* If the error message mentions your database server or redis server, make sure these are running and accessible.
|
||||
|
||||
* If pretix loads fine but certain actions (creating carts, orders, or exports, downloading tickets, sending emails) **take forever**,
|
||||
``pretix-worker`` is not running. Check the output of ``docker logs pretix`` for a docker installation and
|
||||
``journalctl -u pretix-worker.service`` for a manual installation.
|
||||
|
||||
* If the page loads but all **styles are missing**, you probably forgot to update your nginx configuration file after an upgrade of your
|
||||
operating system's python version.
|
||||
|
||||
|
||||
If you are unable to debug the issue any further, please open a **discussion** on GitHub in our `Q&A Forum`_. Do **not** open an issue
|
||||
right away, since most things turn out not to be a bug in pretix but a mistake in your server configuration. Make sure to include
|
||||
relevant log excerpts in your question.
|
||||
|
||||
If you're a pretix Enterprise customer, you can also reach out to support@pretix.eu with your issue right away.
|
||||
|
||||
.. _Q&A Forum: https://github.com/pretix/pretix/discussions/categories/q-a
|
||||
18
doc/admin/index.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
.. _`admindocs`:
|
||||
|
||||
Administrator documentation
|
||||
===========================
|
||||
|
||||
This documentation is for everyone who wants to install pretix on a server.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation/index
|
||||
updates
|
||||
config
|
||||
maintainance
|
||||
scaling
|
||||
errors
|
||||
mysql2postgres
|
||||
indexes
|
||||
83
doc/admin/indexes.rst
Normal file
@@ -0,0 +1,83 @@
|
||||
Additional database indices
|
||||
===========================
|
||||
|
||||
If you have a large pretix database, some features such as search for orders or events might turn pretty slow.
|
||||
For PostgreSQL, we have compiled a list of additional database indexes that you can add to speed things up.
|
||||
Just like any index, they in turn make write operations insignificantly slower and cause the database to use
|
||||
more disk space.
|
||||
|
||||
The indexes aren't automatically created by pretix since Django does not allow us to do so only on PostgreSQL
|
||||
(and they won't work on other databases). Also, they're really not necessary if you're not having tens of
|
||||
thousands of records in your database.
|
||||
|
||||
However, this also means they won't automatically adapt if some of the referred fields change in future updates of pretix
|
||||
and you might need to re-check this page and change them manually.
|
||||
|
||||
Here is the currently recommended set of commands::
|
||||
|
||||
CREATE EXTENSION pg_trgm;
|
||||
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_event_slug
|
||||
ON pretixbase_event
|
||||
USING gin (upper("slug") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_event_name
|
||||
ON pretixbase_event
|
||||
USING gin (upper("name") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_order_code
|
||||
ON pretixbase_order
|
||||
USING gin (upper("code") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_voucher_code
|
||||
ON pretixbase_voucher
|
||||
USING gin (upper("code") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_invoice_nu1
|
||||
ON "pretixbase_invoice" (UPPER("invoice_no"));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_invoice_nu2
|
||||
ON "pretixbase_invoice" (UPPER("full_invoice_no"));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_organizer_name
|
||||
ON pretixbase_organizer
|
||||
USING gin (upper("name") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_organizer_slug
|
||||
ON pretixbase_organizer
|
||||
USING gin (upper("slug") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_order_email
|
||||
ON pretixbase_order
|
||||
USING gin (upper("email") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_order_comment
|
||||
ON pretixbase_order
|
||||
USING gin (upper("comment") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_order_event_date_id
|
||||
ON public.pretixbase_order (event_id, datetime, id);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_name
|
||||
ON pretixbase_orderposition
|
||||
USING gin (upper("attendee_name_cached") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_secret
|
||||
ON pretixbase_orderposition
|
||||
USING gin (upper("secret") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_email
|
||||
ON pretixbase_orderposition
|
||||
USING gin (upper("attendee_email") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_ia_name
|
||||
ON pretixbase_invoiceaddress
|
||||
USING gin (upper("name_cached") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_ia_company
|
||||
ON pretixbase_invoiceaddress
|
||||
USING gin (upper("company") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_email_upper
|
||||
ON public.pretixbase_orderposition (upper((attendee_email)::text));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_voucher_code_upper
|
||||
ON public.pretixbase_voucher (upper((code)::text));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_date_id
|
||||
ON public.pretixbase_logentry (event_id, datetime, id);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_cid_date_id
|
||||
ON public.pretixbase_logentry (event_id, content_type_id, datetime, id);
|
||||
|
||||
|
||||
Also, if you use our ``pretix-shipping`` plugin::
|
||||
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_sa_name
|
||||
ON pretix_shipping_shippingaddress
|
||||
USING gin (upper("name") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_sa_company
|
||||
ON pretix_shipping_shippingaddress
|
||||
USING gin (upper("company") gin_trgm_ops);
|
||||
|
||||
37
doc/admin/installation/dev_version.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
.. highlight:: none
|
||||
|
||||
Installing a development version
|
||||
================================
|
||||
|
||||
If you want to use a feature of pretix that is not yet contained in the last monthly release, you can also
|
||||
install a development version with pretix.
|
||||
|
||||
.. warning:: When in production, we strongly recommend only installing released versions. Development versions might
|
||||
be broken, incompatible to plugins, or in rare cases incompatible to upgrade later on.
|
||||
|
||||
|
||||
Manual installation
|
||||
-------------------
|
||||
|
||||
You can use ``pip`` to update pretix directly to the development branch. Then, upgrade as usual::
|
||||
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install -U "git+https://github.com/pretix/pretix.git#egg=pretix"
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
(venv)$ python -m pretix updatestyles
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
Docker installation
|
||||
-------------------
|
||||
|
||||
To use the latest development version with Docker, first pull it from Docker Hub::
|
||||
|
||||
$ docker pull pretix/standalone:latest
|
||||
|
||||
|
||||
Then change your ``/etc/systemd/system/pretix.service`` file to use the ``:latest`` tag instead of ``:stable`` as well
|
||||
and upgrade as usual::
|
||||
|
||||
$ systemctl restart pretix.service
|
||||
$ docker exec -it pretix.service pretix upgrade
|
||||
333
doc/admin/installation/docker_smallscale.rst
Normal file
@@ -0,0 +1,333 @@
|
||||
.. highlight:: none
|
||||
|
||||
.. _`dockersmallscale`:
|
||||
|
||||
Small-scale deployment with Docker
|
||||
==================================
|
||||
|
||||
This guide describes the installation of a small-scale installation of pretix using docker. By small-scale, we mean
|
||||
that everything is being run on one host and you don't expect thousands of participants trying to get a ticket within
|
||||
a few minutes. In this setup, as many parts of pretix as possible are hidden away in one single docker container.
|
||||
This has some trade-offs in terms of performance and isolation but allows a rather easy installation.
|
||||
|
||||
.. warning:: Even though we try to make it straightforward to run pretix, it still requires some Linux experience to
|
||||
get it right. If you're not feeling comfortable managing a Linux server, check out our hosting and service
|
||||
offers at `pretix.eu`_.
|
||||
|
||||
We tested this guide on the Linux distribution **Debian 11.0** but it should work very similar on other
|
||||
modern distributions, especially on all systemd-based ones.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Please set up the following systems beforehand, we'll not explain them here (but see these links for external
|
||||
installation guides):
|
||||
|
||||
* `Docker`_
|
||||
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
|
||||
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
|
||||
* A `PostgreSQL`_ 11+ database server
|
||||
* A `redis`_ server
|
||||
|
||||
We also recommend that you use a firewall, although this is not a pretix-specific recommendation. If you're new to
|
||||
Linux and firewalls, we recommend that you start with `ufw`_.
|
||||
|
||||
.. note:: Please, do not run pretix without HTTPS encryption. You'll handle user data and thanks to `Let's Encrypt`_
|
||||
SSL certificates can be obtained for free these days. We also *do not* provide support for HTTP-only
|
||||
installations except for evaluation purposes.
|
||||
|
||||
.. warning:: By default, using `ufw` in conjunction will not have any effect. Please make sure to either bind the exposed
|
||||
ports of your docker container explicitly to 127.0.0.1 or configure docker to respect any set up firewall
|
||||
rules.
|
||||
|
||||
On this guide
|
||||
-------------
|
||||
|
||||
All code lines prepended with a ``#`` symbol are commands that you need to execute on your server as ``root`` user;
|
||||
all lines prepended with a ``$`` symbol can also be run by an unprivileged user.
|
||||
|
||||
Data files
|
||||
----------
|
||||
|
||||
First of all, you need to create a directory on your server that pretix can use to store data files and make that
|
||||
directory writable to the user that runs pretix inside the docker container::
|
||||
|
||||
# mkdir /var/pretix-data
|
||||
# chown -R 15371:15371 /var/pretix-data
|
||||
|
||||
Database
|
||||
--------
|
||||
|
||||
Next, we need a database and a database user. We can create these with any kind of database managing tool or directly on
|
||||
our database's shell. Please make sure that UTF8 is used as encoding for the best compatibility. You can check this with
|
||||
the following command::
|
||||
|
||||
# sudo -u postgres psql -c 'SHOW SERVER_ENCODING'
|
||||
|
||||
For PostgreSQL database creation, we would do::
|
||||
|
||||
# sudo -u postgres createuser -P pretix
|
||||
# sudo -u postgres createdb -O pretix pretix
|
||||
|
||||
Make sure that your database listens on the network. If PostgreSQL on the same same host as docker, but not inside a docker container, we recommend that you just listen on the Docker interface by changing the following line in ``/etc/postgresql/<version>/main/postgresql.conf``::
|
||||
|
||||
listen_addresses = 'localhost,172.17.0.1'
|
||||
|
||||
You also need to add a new line to ``/etc/postgresql/<version>/main/pg_hba.conf`` to allow network connections to this user and database::
|
||||
|
||||
host pretix pretix 172.17.0.1/16 md5
|
||||
|
||||
Restart PostgreSQL after you changed these files::
|
||||
|
||||
# systemctl restart postgresql
|
||||
|
||||
If you have a firewall running, you should also make sure that port 5432 is reachable from the ``172.17.0.1/16`` subnet.
|
||||
|
||||
Redis
|
||||
-----
|
||||
|
||||
For caching and messaging in small-scale setups, pretix recommends using redis. In this small-scale setup we assume a
|
||||
redis instance to be running on the same host. To avoid the hassle with network configurations and firewalls, we
|
||||
recommend connecting to redis via a unix socket. To enable redis on unix sockets, add the following to your
|
||||
``/etc/redis/redis.conf``::
|
||||
|
||||
unixsocket /var/run/redis/redis.sock
|
||||
unixsocketperm 777
|
||||
|
||||
Now restart redis-server::
|
||||
|
||||
# systemctl restart redis-server
|
||||
|
||||
In this setup, systemd will delete ``/var/run/redis`` on every redis restart, which will cause issues with pretix. To
|
||||
prevent this, you can execute::
|
||||
|
||||
# systemctl edit redis-server
|
||||
|
||||
And insert the following::
|
||||
|
||||
[Service]
|
||||
# Keep the directory around so that pretix.service in docker does not need to be
|
||||
# restarted when redis is restarted.
|
||||
RuntimeDirectoryPreserve=yes
|
||||
|
||||
.. warning:: Setting the socket permissions to 777 is a possible security problem. If you have untrusted users on your
|
||||
system or have high security requirements, please don't do this and let redis listen to a TCP socket
|
||||
instead. We recommend the socket approach because the TCP socket in combination with docker's networking
|
||||
can easily become an even worse security hole when configured slightly wrong. Read more about security
|
||||
on the `redis website`_.
|
||||
|
||||
Another possible solution is to run `redis in docker`_ and link the containers using docker's networking
|
||||
features.
|
||||
|
||||
Config file
|
||||
-----------
|
||||
|
||||
We now create a config directory and config file for pretix::
|
||||
|
||||
# mkdir /etc/pretix
|
||||
# touch /etc/pretix/pretix.cfg
|
||||
# chown -R 15371:15371 /etc/pretix/
|
||||
# chmod 0700 /etc/pretix/pretix.cfg
|
||||
|
||||
Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following content (adjusted to your environment)::
|
||||
|
||||
[pretix]
|
||||
instance_name=My pretix installation
|
||||
url=https://pretix.mydomain.com
|
||||
currency=EUR
|
||||
; DO NOT change the following value, it has to be set to the location of the
|
||||
; directory *inside* the docker container
|
||||
datadir=/data
|
||||
trust_x_forwarded_for=on
|
||||
trust_x_forwarded_proto=on
|
||||
|
||||
[database]
|
||||
backend=postgresql
|
||||
name=pretix
|
||||
user=pretix
|
||||
; Replace with the password you chose above
|
||||
password=*********
|
||||
; In most docker setups, 172.17.0.1 is the address of the docker host. Adjust
|
||||
; this to wherever your database is running, e.g. the name of a linked container.
|
||||
host=172.17.0.1
|
||||
|
||||
[mail]
|
||||
; See config file documentation for more options
|
||||
from=tickets@yourdomain.com
|
||||
; This is the default IP address of your docker host in docker's virtual
|
||||
; network. Make sure postfix listens on this address.
|
||||
host=172.17.0.1
|
||||
|
||||
[redis]
|
||||
location=unix:///var/run/redis/redis.sock?db=0
|
||||
; Remove the following line if you are unsure about your redis' security
|
||||
; to reduce impact if redis gets compromised.
|
||||
sessions=true
|
||||
|
||||
[celery]
|
||||
backend=redis+socket:///var/run/redis/redis.sock?virtual_host=1
|
||||
broker=redis+socket:///var/run/redis/redis.sock?virtual_host=2
|
||||
|
||||
See :ref:`email configuration <mail-settings>` to learn more about configuring mail features.
|
||||
|
||||
Docker image and service
|
||||
------------------------
|
||||
|
||||
First of all, download the latest stable pretix image by running::
|
||||
|
||||
$ docker pull pretix/standalone:stable
|
||||
|
||||
We recommend starting the docker container using systemd to make sure it runs correctly after a reboot. Create a file
|
||||
named ``/etc/systemd/system/pretix.service`` with the following content::
|
||||
|
||||
[Unit]
|
||||
Description=pretix
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=0
|
||||
ExecStartPre=-/usr/bin/docker kill %n
|
||||
ExecStartPre=-/usr/bin/docker rm %n
|
||||
ExecStart=/usr/bin/docker run --name %n -p 127.0.0.1:8345:80 \
|
||||
-v /var/pretix-data:/data \
|
||||
-v /etc/pretix:/etc/pretix \
|
||||
-v /var/run/redis:/var/run/redis \
|
||||
--sysctl net.core.somaxconn=4096 \
|
||||
pretix/standalone:stable all
|
||||
ExecStop=/usr/bin/docker stop %n
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
You can now run the following commands
|
||||
to enable and start the service::
|
||||
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable pretix
|
||||
# systemctl start pretix
|
||||
|
||||
Cronjob
|
||||
-------
|
||||
|
||||
You need to set up a cronjob that runs the management command ``runperiodic``. The exact interval is not important
|
||||
but should be something between every minute and every hour. You could for example configure cron like this::
|
||||
|
||||
15,45 * * * * /usr/bin/docker exec pretix.service pretix cron
|
||||
|
||||
The cronjob may run as any user that can use the docker daemon.
|
||||
|
||||
SSL
|
||||
---
|
||||
|
||||
The following snippet is an example on how to configure a nginx proxy for pretix::
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 ipv6only=on default_server;
|
||||
server_name pretix.mydomain.com;
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen 443 default_server;
|
||||
listen [::]:443 ipv6only=on default_server;
|
||||
server_name pretix.mydomain.com;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate /path/to/cert.chain.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8345;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
We recommend reading about setting `strong encryption settings`_ for your web server.
|
||||
|
||||
Next steps
|
||||
----------
|
||||
|
||||
Yay, you are done! You should now be able to reach pretix at https://pretix.yourdomain.com/control/ and log in as
|
||||
*admin@localhost* with a password of *admin*. Don't forget to change that password! Create an organizer first, then
|
||||
create an event and start selling tickets!
|
||||
|
||||
You should probably read :ref:`maintainance` next.
|
||||
|
||||
.. _`docker_updates`:
|
||||
|
||||
Updates
|
||||
-------
|
||||
|
||||
.. warning:: While we try hard not to break things, **please perform a backup before every upgrade**.
|
||||
|
||||
Updates are fairly simple, but require at least a short downtime::
|
||||
|
||||
# docker pull pretix/standalone:stable
|
||||
# systemctl restart pretix.service
|
||||
# docker exec -it pretix.service pretix upgrade
|
||||
|
||||
Restarting the service can take a few seconds, especially if the update requires changes to the database.
|
||||
Replace ``stable`` above with a specific version number like ``1.0`` or with ``latest`` for the development
|
||||
version, if you want to.
|
||||
|
||||
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to.
|
||||
|
||||
.. _`docker_plugininstall`:
|
||||
|
||||
Install a plugin
|
||||
----------------
|
||||
|
||||
To install a plugin, you need to build your own docker image. To do so, create a new directory and place a file
|
||||
named ``Dockerfile`` in it. The Dockerfile could look like this (replace ``pretix-passbook`` with the plugins of your
|
||||
choice)::
|
||||
|
||||
FROM pretix/standalone:stable
|
||||
USER root
|
||||
RUN pip3 install pretix-passbook
|
||||
USER pretixuser
|
||||
RUN cd /pretix/src && make production
|
||||
|
||||
Then, go to that directory and build the image::
|
||||
|
||||
$ docker build . -t mypretix
|
||||
|
||||
You can now use that image ``mypretix`` instead of ``pretix/standalone`` in your service file (see above). Be sure
|
||||
to re-build your custom image after you pulled ``pretix/standalone`` if you want to perform an update.
|
||||
|
||||
Scaling up
|
||||
----------
|
||||
|
||||
If you need to scale to multiple machines, please first read our :ref:`scaling guide <scaling>`.
|
||||
|
||||
If you run the official docker container on multiple machines, it is recommended to set the environment
|
||||
variable ``AUTOMIGRATE=skip`` on all containers and run ``docker exec -it pretix.service pretix migrate``
|
||||
on one machine after each upgrade manually, otherwise multiple containers might try to upgrade the
|
||||
database schema at the same time.
|
||||
|
||||
To run only the ``pretix-web`` component of pretix as well as a nginx server serving static files, you
|
||||
can invoke the container with ``docker run … pretix/standalone:stable web`` (instead of ``all``). You
|
||||
can adjust the number of ``gunicorn`` processes with the ``NUM_WORKERS`` environment variable (defaults to
|
||||
two times the number of CPUs detected).
|
||||
|
||||
To run only ``pretix-worker``, you can run ``docker run … pretix/standalone:stable taskworker``. You can
|
||||
also pass arguments to limit the worker to specific queues or to change the number of concurrent task
|
||||
workers, e.g. ``docker run … taskworker -Q notifications --concurrency 32``.
|
||||
|
||||
|
||||
.. _Docker: https://docs.docker.com/engine/installation/linux/debian/
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
|
||||
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
|
||||
.. _Let's Encrypt: https://letsencrypt.org/
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _redis website: https://redis.io/topics/security
|
||||
.. _redis in docker: https://hub.docker.com/r/_/redis/
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
84
doc/admin/installation/enterprise.rst
Normal file
@@ -0,0 +1,84 @@
|
||||
.. highlight:: none
|
||||
|
||||
Installing pretix Enterprise plugins
|
||||
====================================
|
||||
|
||||
If you want to use a feature of pretix that is part of our commercial offering pretix Enterprise, you need to follow
|
||||
some extra steps. Installation works similar to normal pretix plugins, but involves a few extra steps.
|
||||
|
||||
Buying the license
|
||||
------------------
|
||||
|
||||
To obtain a license, please get in touch at sales@pretix.eu. Please let us know how many tickets you roughly intend
|
||||
to sell per year and how many servers you want to use the plugin on. We recommend having a look at our `price list`_
|
||||
first.
|
||||
|
||||
|
||||
Manual installation
|
||||
-------------------
|
||||
|
||||
First, generate an SSH key for the system user that you install pretix as. In our tutorial, that would be the user
|
||||
``pretix``. Choose an empty passphrase::
|
||||
|
||||
# su pretix
|
||||
$ ssh-keygen
|
||||
Generating public/private rsa key pair.
|
||||
Enter file in which to save the key (/var/pretix/.ssh/id_rsa):
|
||||
Enter passphrase (empty for no passphrase):
|
||||
Enter same passphrase again:
|
||||
Your identification has been saved in /var/pretix/.ssh/id_rsa.
|
||||
Your public key has been saved in /var/pretix/.ssh/id_rsa.pub.
|
||||
|
||||
Next, send the content of the *public* key to your sales representative at pretix::
|
||||
|
||||
$ cat /var/pretix/.ssh/id_rsa.pub
|
||||
ssh-rsa AAAAB3N...744HZawHlD pretix@foo
|
||||
|
||||
After we configured your key in our system, you can install the plugin directly using ``pip`` from the URL we told
|
||||
you, for example::
|
||||
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install -U "git+ssh://git@code.rami.io:10022/pretix/pretix-slack.git@stable#egg=pretix-slack"
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
Docker installation
|
||||
-------------------
|
||||
|
||||
To install a plugin, you need to build your own docker image. To do so, create a new directory to work in. As a first
|
||||
step, generate a new SSH key in that directory to use for authentication with us::
|
||||
|
||||
$ cd /home/me/mypretixdocker
|
||||
$ ssh-keygen -N "" -f id_pretix_enterprise
|
||||
|
||||
Next, send the content of the *public* key to your sales representative at pretix::
|
||||
|
||||
$ cat id_pretix_enterprise.pub
|
||||
ssh-rsa AAAAB3N...744HZawHlD pretix@foo
|
||||
|
||||
After we configured your key in our system, you can add a ``Dockerfile`` in your directory that includes the newly
|
||||
generated key and installs the plugin from the URL we told you::
|
||||
|
||||
FROM pretix/standalone:stable
|
||||
USER root
|
||||
COPY id_pretix_enterprise /root/.ssh/id_rsa
|
||||
COPY id_pretix_enterprise.pub /root/.ssh/id_rsa.pub
|
||||
RUN chmod -R 0600 /root/.ssh && \
|
||||
mkdir -p /etc/ssh && \
|
||||
ssh-keyscan -t rsa -p 10022 code.rami.io >> /root/.ssh/known_hosts && \
|
||||
echo StrictHostKeyChecking=no >> /root/.ssh/config && \
|
||||
DJANGO_SETTINGS_MODULE= pip3 install -U "git+ssh://git@code.rami.io:10022/pretix/pretix-slack.git@stable#egg=pretix-slack" && \
|
||||
cd /pretix/src && \
|
||||
sudo -u pretixuser make production
|
||||
USER pretixuser
|
||||
|
||||
Then, build the image for docker::
|
||||
|
||||
$ docker build -t mypretix
|
||||
|
||||
You can now use that image ``mypretix`` instead of ``pretix/standalone:stable`` in your ``/etc/systemd/system/pretix.service``
|
||||
service file. Be sure to re-build your custom image after you pulled ``pretix/standalone`` if you want to perform an
|
||||
update to a new version of pretix.
|
||||
|
||||
.. _price list: https://pretix.eu/about/en/pricing
|
||||
39
doc/admin/installation/general.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
.. highlight:: ini
|
||||
|
||||
.. spelling:word-list:: SQL
|
||||
|
||||
General remarks
|
||||
===============
|
||||
|
||||
Requirements
|
||||
------------
|
||||
To use pretix, you will need the following things:
|
||||
|
||||
* **pretix** and the python packages it depends on
|
||||
|
||||
* An **WSGI application server** (we recommend gunicorn)
|
||||
|
||||
* A periodic task runner, e.g. ``cron``
|
||||
|
||||
* **A database**. This needs to be a SQL-based that is supported by Django. We highly recommend to either
|
||||
go for **PostgreSQL**. If you do not provide one, pretix will run on SQLite, which is useful
|
||||
for evaluation and development purposes.
|
||||
|
||||
.. warning:: Do not ever use SQLite in production. It will break.
|
||||
|
||||
* A **reverse proxy**. pretix needs to deliver some static content to your users (e.g. CSS, images, ...). While pretix
|
||||
is capable of doing this, having this handled by a proper web server like **nginx** or **Apache** will be much
|
||||
faster. Also, you need a proxying web server in front to provide SSL encryption.
|
||||
|
||||
.. warning:: Do not ever run without SSL in production. Your users deserve encrypted connections and thanks to
|
||||
`Let's Encrypt`_ SSL certificates can be obtained for free these days.
|
||||
|
||||
* A **redis** server. This will be used for caching, session storage and task queuing.
|
||||
|
||||
.. warning:: pretix can run without redis, however this is only intended for development and should never be
|
||||
used in production.
|
||||
|
||||
* Optionally: RabbitMQ or memcached. Both of them might provide speedups, but if they are not present,
|
||||
redis will take over their job.
|
||||
|
||||
.. _Let's Encrypt: https://letsencrypt.org/
|
||||
16
doc/admin/installation/index.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
.. _`installation`:
|
||||
|
||||
Installation guide
|
||||
==================
|
||||
|
||||
We provide you with multiple installation guides for multiple types of setups so you can choose the one appropriate
|
||||
for your needs.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
general
|
||||
docker_smallscale
|
||||
manual_smallscale
|
||||
dev_version
|
||||
enterprise
|
||||
335
doc/admin/installation/manual_smallscale.rst
Normal file
@@ -0,0 +1,335 @@
|
||||
.. highlight:: none
|
||||
|
||||
Small-scale manual deployment
|
||||
=============================
|
||||
|
||||
This guide describes the installation of a small-scale installation of pretix from source. By small-scale, we mean
|
||||
that everything is being run on one host and you don't expect thousands of participants trying to get a ticket within
|
||||
a few minutes. In this setup, you will have to perform a number of manual steps. If you prefer using a container
|
||||
solution with many things readily set-up, look at :ref:`dockersmallscale`.
|
||||
|
||||
.. warning:: Even though we try to make it straightforward to run pretix, it still requires some Linux experience to
|
||||
get it right. If you're not feeling comfortable managing a Linux server, check out our hosting and service
|
||||
offers at `pretix.eu`_.
|
||||
|
||||
We tested this guide on the Linux distribution **Debian 11.6** but it should work very similar on other
|
||||
modern distributions, especially on all systemd-based ones.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Please set up the following systems beforehand, we'll not explain them here in detail (but see these links for external
|
||||
installation guides):
|
||||
|
||||
* A python 3.9+ installation
|
||||
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
|
||||
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
|
||||
* A `PostgreSQL`_ 11+ database server
|
||||
* A `redis`_ server
|
||||
* A `nodejs`_ installation
|
||||
|
||||
We also recommend that you use a firewall, although this is not a pretix-specific recommendation. If you're new to
|
||||
Linux and firewalls, we recommend that you start with `ufw`_.
|
||||
|
||||
.. note:: Please, do not run pretix without HTTPS encryption. You'll handle user data and thanks to `Let's Encrypt`_
|
||||
SSL certificates can be obtained for free these days. We also *do not* provide support for HTTP-only
|
||||
installations except for evaluation purposes.
|
||||
|
||||
Unix user
|
||||
---------
|
||||
|
||||
As we do not want to run pretix as root, we first create a new unprivileged user::
|
||||
|
||||
# adduser pretix --disabled-password --home /var/pretix
|
||||
|
||||
In this guide, all code lines prepended with a ``#`` symbol are commands that you need to execute on your server as
|
||||
``root`` user (e.g. using ``sudo``); all lines prepended with a ``$`` symbol should be run by the unprivileged user.
|
||||
|
||||
Database
|
||||
--------
|
||||
|
||||
Having the database server installed, we still need a database and a database user. We can create these with any kind
|
||||
of database managing tool or directly on our database's shell. Please make sure that UTF8 is used as encoding for the
|
||||
best compatibility. You can check this with the following command::
|
||||
|
||||
# sudo -u postgres psql -c 'SHOW SERVER_ENCODING'
|
||||
|
||||
For PostgreSQL database creation, we would do::
|
||||
|
||||
# sudo -u postgres createuser pretix
|
||||
# sudo -u postgres createdb -O pretix pretix
|
||||
|
||||
Package dependencies
|
||||
--------------------
|
||||
|
||||
To build and run pretix, you will need the following debian packages::
|
||||
|
||||
# apt-get install git build-essential python-dev python3-venv python3 python3-pip \
|
||||
python3-dev libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
|
||||
gettext libpq-dev libjpeg-dev libopenjp2-7-dev
|
||||
|
||||
Config file
|
||||
-----------
|
||||
|
||||
We now create a config directory and config file for pretix::
|
||||
|
||||
# mkdir /etc/pretix
|
||||
# touch /etc/pretix/pretix.cfg
|
||||
# chown -R pretix:pretix /etc/pretix/
|
||||
# chmod 0600 /etc/pretix/pretix.cfg
|
||||
|
||||
Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following content (adjusted to your environment)::
|
||||
|
||||
[pretix]
|
||||
instance_name=My pretix installation
|
||||
url=https://pretix.mydomain.com
|
||||
currency=EUR
|
||||
datadir=/var/pretix/data
|
||||
trust_x_forwarded_for=on
|
||||
trust_x_forwarded_proto=on
|
||||
|
||||
[database]
|
||||
backend=postgresql
|
||||
name=pretix
|
||||
user=pretix
|
||||
; For PostgreSQL on the same host, we don't need a password because we can use
|
||||
; peer authentication if our PostgreSQL user matches our unix user.
|
||||
password=
|
||||
; For local postgres authentication, you can leave it empty
|
||||
host=
|
||||
|
||||
[mail]
|
||||
; See config file documentation for more options
|
||||
from=tickets@yourdomain.com
|
||||
host=127.0.0.1
|
||||
|
||||
[redis]
|
||||
location=redis://127.0.0.1/0
|
||||
sessions=true
|
||||
|
||||
[celery]
|
||||
backend=redis://127.0.0.1/1
|
||||
broker=redis://127.0.0.1/2
|
||||
|
||||
See :ref:`email configuration <mail-settings>` to learn more about configuring mail features.
|
||||
|
||||
Install pretix from PyPI
|
||||
------------------------
|
||||
|
||||
Now we will install pretix itself. The following steps are to be executed as the ``pretix`` user. Before we
|
||||
actually install pretix, we will create a virtual environment to isolate the python packages from your global
|
||||
python installation::
|
||||
|
||||
$ python3 -m venv /var/pretix/venv
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install -U pip setuptools wheel
|
||||
|
||||
We now install pretix, its direct dependencies and gunicorn::
|
||||
|
||||
(venv)$ pip3 install pretix gunicorn
|
||||
|
||||
Note that you need Python 3.9 or newer. You can find out your Python version using ``python -V``.
|
||||
|
||||
We also need to create a data directory::
|
||||
|
||||
(venv)$ mkdir -p /var/pretix/data/media
|
||||
|
||||
Finally, we compile static files and translation data and create the database structure::
|
||||
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
|
||||
|
||||
Start pretix as a service
|
||||
-------------------------
|
||||
|
||||
We recommend starting pretix using systemd to make sure it runs correctly after a reboot. Create a file
|
||||
named ``/etc/systemd/system/pretix-web.service`` with the following content::
|
||||
|
||||
[Unit]
|
||||
Description=pretix web service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=pretix
|
||||
Group=pretix
|
||||
Environment="VIRTUAL_ENV=/var/pretix/venv"
|
||||
Environment="PATH=/var/pretix/venv/bin:/usr/local/bin:/usr/bin:/bin"
|
||||
ExecStart=/var/pretix/venv/bin/gunicorn pretix.wsgi \
|
||||
--name pretix --workers 5 \
|
||||
--max-requests 1200 --max-requests-jitter 50 \
|
||||
--log-level=info --bind=127.0.0.1:8345
|
||||
WorkingDirectory=/var/pretix
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
For background tasks we need a second service ``/etc/systemd/system/pretix-worker.service`` with the following content::
|
||||
|
||||
[Unit]
|
||||
Description=pretix background worker
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=pretix
|
||||
Group=pretix
|
||||
Environment="VIRTUAL_ENV=/var/pretix/venv"
|
||||
Environment="PATH=/var/pretix/venv/bin:/usr/local/bin:/usr/bin:/bin"
|
||||
ExecStart=/var/pretix/venv/bin/celery -A pretix.celery_app worker -l info
|
||||
WorkingDirectory=/var/pretix
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
You can now run the following commands to enable and start the services::
|
||||
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable pretix-web pretix-worker
|
||||
# systemctl start pretix-web pretix-worker
|
||||
|
||||
|
||||
Cronjob
|
||||
-------
|
||||
|
||||
You need to set up a cronjob that runs the management command ``runperiodic``. The exact interval is not important
|
||||
but should be something between every minute and every hour. You could for example configure cron like this::
|
||||
|
||||
15,45 * * * * export PATH=/var/pretix/venv/bin:$PATH && cd /var/pretix && python -m pretix runperiodic
|
||||
|
||||
The cronjob should run as the ``pretix`` user (``crontab -e -u pretix``).
|
||||
|
||||
SSL
|
||||
---
|
||||
|
||||
The following snippet is an example on how to configure a nginx proxy for pretix::
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 ipv6only=on default_server;
|
||||
server_name pretix.mydomain.com;
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen 443 default_server;
|
||||
listen [::]:443 ipv6only=on default_server;
|
||||
server_name pretix.mydomain.com;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate /path/to/cert.chain.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
add_header Referrer-Policy same-origin;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8345;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
|
||||
location /media/ {
|
||||
alias /var/pretix/data/media/;
|
||||
expires 7d;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ^~ /media/cachedfiles {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location ^~ /media/invoices {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /var/pretix/venv/lib/python3.10/site-packages/pretix/static.dist/;
|
||||
access_log off;
|
||||
expires 365d;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
}
|
||||
|
||||
.. note:: Remember to replace the ``python3.10`` in the ``/static/`` path in the config
|
||||
above with your python version.
|
||||
|
||||
We recommend reading about setting `strong encryption settings`_ for your web server.
|
||||
|
||||
Next steps
|
||||
----------
|
||||
|
||||
Yay, you are done! You should now be able to reach pretix at https://pretix.yourdomain.com/control/ and log in as
|
||||
*admin@localhost* with a password of *admin*. Don't forget to change that password! Create an organizer first, then
|
||||
create an event and start selling tickets!
|
||||
|
||||
You should probably read :ref:`maintainance` next.
|
||||
|
||||
.. _`manual_updates`:
|
||||
|
||||
Updates
|
||||
-------
|
||||
|
||||
.. warning:: While we try hard not to break things, **please perform a backup before every upgrade**.
|
||||
|
||||
To upgrade to a new pretix release, pull the latest code changes and run the following commands::
|
||||
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install -U --upgrade-strategy eager pretix gunicorn
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
(venv)$ python -m pretix updatestyles
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to.
|
||||
|
||||
.. _`manual_plugininstall`:
|
||||
|
||||
Install a plugin
|
||||
----------------
|
||||
|
||||
To install a plugin, just use ``pip``! Depending on the plugin, you should probably apply database migrations and
|
||||
rebuild the static files afterwards. Replace ``pretix-passbook`` with the plugin of your choice in the following
|
||||
example::
|
||||
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install pretix-passbook
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
System updates
|
||||
--------------
|
||||
|
||||
After system updates, such as updates to a new Ubuntu or Debian release, you might be using a new Python version.
|
||||
That's great, but requires some adjustments. First, adjust any old version paths in your nginx configuration file.
|
||||
Then, re-create your Python environment::
|
||||
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 freeze > /tmp/pip-backup.txt
|
||||
$ rm -rf /var/pretix/venv
|
||||
$ python3 -m venv /var/pretix/venv
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ pip3 install -U pip wheel setuptools
|
||||
(venv)$ pip3 install -r /tmp/pip-backup.txt
|
||||
|
||||
Then, proceed like after any plugin installation::
|
||||
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
(venv)$ python -m pretix updatestyles
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
|
||||
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
|
||||
.. _Let's Encrypt: https://letsencrypt.org/
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
.. _nodejs: https://github.com/nodesource/distributions/blob/master/README.md#deb
|
||||
108
doc/admin/maintainance.rst
Normal file
@@ -0,0 +1,108 @@
|
||||
.. highlight:: ini
|
||||
|
||||
.. _`maintainance`:
|
||||
|
||||
Backups and Monitoring
|
||||
======================
|
||||
|
||||
If you host your own pretix instance, you also need to care about the availability
|
||||
of your service and the safety of your data yourself. This page gives you some
|
||||
information that you might need to do so properly.
|
||||
|
||||
.. _`backups`:
|
||||
|
||||
Backups
|
||||
-------
|
||||
|
||||
There are essentially two things which you should create backups of:
|
||||
|
||||
Database
|
||||
Your SQL database. This is critical and you should **absolutely always create automatic
|
||||
backups of your database**. There are tons of tutorials on the internet on how to do this,
|
||||
and the exact process depends on the choice of your database. For PostgreSQL, see the
|
||||
``pg_dump`` tool. You probably want to create a cronjob that does the backups for you on a
|
||||
regular schedule.
|
||||
|
||||
Data directory
|
||||
The data directory of your pretix configuration might contain some things that you should
|
||||
back up. If you did not specify a secret in your config file, back up the ``.secret`` text
|
||||
file in the data directory. If you lose your secret, all currently active user sessions,
|
||||
password reset links and similar things will be rendered invalid. Also, you probably want
|
||||
to backup the ``media`` subdirectory of the data directory which contains all user-uploaded
|
||||
and generated files. This includes files you could in theory regenerate (ticket downloads)
|
||||
but also files that you might be legally required to keep (invoice PDFs) or files that you
|
||||
would need to re-upload (event logos, product pictures, etc.). It is up to you if you
|
||||
create regular backups of this data, but we strongly advise you to do so. You can create
|
||||
backups e.g. using ``rsync``. There is a lot of information on the internet on how to create
|
||||
backups of folders on a Linux machine.
|
||||
|
||||
There is no need to create backups of the redis database, if you use it. We only use it for
|
||||
non-critical, temporary or cached data.
|
||||
|
||||
Uptime monitoring
|
||||
-----------------
|
||||
|
||||
To monitor whether your pretix instance is running, you can issue a GET request to
|
||||
``https://pretix.mydomain.com/healthcheck/``. This endpoint tests if the connection to the
|
||||
database, to the configured cache and to redis (if used) is working correctly. If everything
|
||||
appears to work fine, an empty response with status code ``200`` is returned.
|
||||
If there is a problem, a status code in the ``5xx`` range will be returned.
|
||||
|
||||
.. _`perf-monitoring`:
|
||||
|
||||
Performance monitoring
|
||||
----------------------
|
||||
|
||||
If you want to generate detailed performance statistics of your pretix installation, there is an
|
||||
endpoint at ``https://pretix.mydomain.com/metrics`` (no slash at the end) which returns a
|
||||
number of values in the text format understood by monitoring tools like Prometheus_. This data
|
||||
is only collected and exposed if you enable it in the :ref:`metrics-settings` section of your
|
||||
pretix configuration. You can also configure basic auth credentials there to protect your
|
||||
statistics against unauthorized access. The data is temporarily collected in redis, so the
|
||||
performance impact of this feature depends on the connection to your redis database.
|
||||
|
||||
Currently, mostly response times of HTTP requests and background tasks are exposed.
|
||||
|
||||
If you want to go even further, you can set the ``profile`` option in the :ref:`django-settings`
|
||||
section to a value between 0 and 1. If you set it for example to 0.1, then 10% of your requests
|
||||
(randomly selected) will be run with cProfile_ activated. The profiling results will be saved
|
||||
to your data directory. As this might impact performance significantly and writes a lot of data
|
||||
to disk, we recommend to only enable it for a small number of requests -- and only if you are
|
||||
really interested in the results.
|
||||
|
||||
Available metrics
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The metrics available in pretix follow the standard `metric types`_ from the Prometheus world.
|
||||
Currently, the following metrics are exported:
|
||||
|
||||
pretix_view_requests_total
|
||||
Counter. Counts requests to Django views, labeled with the resolved ``url_name``, the used
|
||||
HTTP ``method`` and the ``status_code`` returned.
|
||||
|
||||
pretix_view_durations_seconds
|
||||
Histogram. Measures duration of requests to Django views, labeled with the resolved
|
||||
``url_name``, the used HTTP ``method`` and the ``status_code`` returned.
|
||||
|
||||
pretix_task_runs_total
|
||||
Counter. Counts executions of background tasks, labeled with the ``task_name`` and the
|
||||
``status``. The latter can be ``success``, ``error`` or ``expected-error``.
|
||||
|
||||
pretix_task_duration_seconds
|
||||
Histogram. Measures duration of successful background task executions, labeled with the
|
||||
``task_name``.
|
||||
|
||||
pretix_model_instances
|
||||
Gauge. Measures number of instances of a certain model within the database, labeled with
|
||||
the ``model`` name. Starting with pretix 3.11, these numbers might only be approximate for
|
||||
most tables when running on PostgreSQL to mitigate performance impact.
|
||||
|
||||
pretix_celery_tasks_queued_count
|
||||
The number of background tasks in the worker queue, labeled with ``queue``.
|
||||
|
||||
pretix_celery_tasks_queued_age_seconds
|
||||
The age of the longest-waiting in the worker queue in seconds, labeled with ``queue``.
|
||||
|
||||
.. _metric types: https://prometheus.io/docs/concepts/metric_types/
|
||||
.. _Prometheus: https://prometheus.io/
|
||||
.. _cProfile: https://docs.python.org/3/library/profile.html
|
||||
241
doc/admin/mysql2postgres.rst
Normal file
@@ -0,0 +1,241 @@
|
||||
.. highlight:: none
|
||||
|
||||
Migrating from MySQL/MariaDB to PostgreSQL
|
||||
==========================================
|
||||
|
||||
Our recommended database for all production installations is PostgreSQL. Support for MySQL/MariaDB has been removed
|
||||
in newer pretix releases.
|
||||
|
||||
In order to follow this guide, your pretix installation needs to be a version that fully supports MySQL/MariaDB. If you
|
||||
already upgraded to pretix 5.0 or later, downgrade back to the last 4.x release using ``pip``.
|
||||
|
||||
.. note:: We have tested this guide carefully, but we can't assume any liability for its correctness. The data loss
|
||||
risk should be low as long as pretix is not running while you do the migration. If you are a pretix Enterprise
|
||||
customer, feel free to reach out in advance if you want us to support you along the way.
|
||||
|
||||
Update database schema
|
||||
----------------------
|
||||
|
||||
Before you start, make sure your database schema is up to date::
|
||||
|
||||
# sudo -u pretix -s
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ python -m pretix migrate
|
||||
|
||||
Install PostgreSQL
|
||||
------------------
|
||||
|
||||
Now, install and set up a PostgreSQL server. For a local installation on Debian or Ubuntu, use::
|
||||
|
||||
# apt install postgresql
|
||||
|
||||
Having the database server installed, we still need a database and a database user. We can create these with any kind
|
||||
of database managing tool or directly on our database's shell. Please make sure that UTF8 is used as encoding for the
|
||||
best compatibility. You can check this with the following command::
|
||||
|
||||
# sudo -u postgres psql -c 'SHOW SERVER_ENCODING'
|
||||
|
||||
Without Docker
|
||||
""""""""""""""
|
||||
|
||||
For our standard manual installation, create the database and user like this::
|
||||
|
||||
# sudo -u postgres createuser pretix
|
||||
# sudo -u postgres createdb -O pretix pretix
|
||||
|
||||
With Docker
|
||||
"""""""""""
|
||||
|
||||
For our standard docker installation, create the database and user like this::
|
||||
|
||||
# sudo -u postgres createuser -P pretix
|
||||
# sudo -u postgres createdb -O pretix pretix
|
||||
|
||||
Make sure that your database listens on the network. If PostgreSQL on the same same host as docker, but not inside a docker container, we recommend that you listen on the Docker interface by changing the following line in ``/etc/postgresql/<version>/main/postgresql.conf``::
|
||||
|
||||
listen_addresses = 'localhost,172.17.0.1'
|
||||
|
||||
You also need to add a new line to ``/etc/postgresql/<version>/main/pg_hba.conf`` to allow network connections to this user and database::
|
||||
|
||||
host pretix pretix 172.17.0.1/16 md5
|
||||
|
||||
Restart PostgreSQL after you changed these files::
|
||||
|
||||
# systemctl restart postgresql
|
||||
|
||||
If you have a firewall running, you should also make sure that port 5432 is reachable from the ``172.17.0.1/16`` subnet.
|
||||
|
||||
Of course, instead of all this you can also run a PostgreSQL docker container and link it to the pretix container.
|
||||
|
||||
Stop pretix
|
||||
-----------
|
||||
|
||||
To prevent any more changes to your data, stop pretix from running::
|
||||
|
||||
# systemctl stop pretix-web pretix-worker
|
||||
|
||||
Change configuration
|
||||
--------------------
|
||||
|
||||
Change the database configuration in your ``/etc/pretix/pretix.cfg`` file::
|
||||
|
||||
[database]
|
||||
backend=postgresql
|
||||
name=pretix
|
||||
user=pretix
|
||||
password= ; only required for docker or remote database, can be kept empty for local auth
|
||||
host= ; set to 172.17.0.1 in docker setup, keep empty for local auth
|
||||
|
||||
|
||||
Create database schema
|
||||
-----------------------
|
||||
|
||||
To create the schema in your new PostgreSQL database, use the following commands::
|
||||
|
||||
# sudo -u pretix -s
|
||||
$ source /var/pretix/venv/bin/activate
|
||||
(venv)$ python -m pretix migrate
|
||||
|
||||
|
||||
Migrate your data
|
||||
-----------------
|
||||
|
||||
Install ``pgloader``::
|
||||
|
||||
# apt install pgloader
|
||||
|
||||
.. note::
|
||||
|
||||
If you are using Ubuntu 20.04, the ``pgloader`` version from the repositories seems to be incompatible with PostgreSQL
|
||||
12+. You can install ``pgloader`` from the `PostgreSQL repositories`_ instead.
|
||||
See also `this discussion <https://github.com/pretix/pretix/issues/3090>`_.
|
||||
|
||||
Create a new file ``/tmp/pretix.load``, replacing the MySQL and PostgreSQL connection strings with the correct user names, passwords, and/or database names::
|
||||
|
||||
LOAD DATABASE
|
||||
FROM mysql://pretix:password@localhost/pretix -- replace with mysql://username:password@hostname/dbname
|
||||
INTO postgresql:///pretix -- replace with dbname
|
||||
|
||||
WITH data only, include no drop, truncate, disable triggers,
|
||||
create no indexes, drop indexes, reset sequences
|
||||
|
||||
ALTER SCHEMA 'pretix' RENAME TO 'public' -- replace pretix with the name of the MySQL database
|
||||
|
||||
ALTER TABLE NAMES MATCHING ~/.*/
|
||||
SET SCHEMA 'public'
|
||||
|
||||
SET timezone TO '+00:00'
|
||||
|
||||
SET PostgreSQL PARAMETERS
|
||||
maintenance_work_mem to '128MB',
|
||||
work_mem to '12MB';
|
||||
|
||||
Then, run::
|
||||
|
||||
# sudo -u postgres pgloader /tmp/pretix.load
|
||||
|
||||
The output should end with a table summarizing the results for every table. You can ignore warnings about type casts
|
||||
and missing constraints.
|
||||
|
||||
Afterwards, delete the file again::
|
||||
|
||||
# rm -rf /tmp/pretix.load
|
||||
|
||||
Start pretix
|
||||
------------
|
||||
|
||||
Now, restart pretix. Maybe stop your MySQL server as a verification step that you are no longer using it::
|
||||
|
||||
# systemctl stop mariadb
|
||||
# systemctl start pretix-web pretix-worker
|
||||
|
||||
And you're done! After you've verified everything has been copied correctly, you can delete the old MySQL database.
|
||||
|
||||
.. note:: Don't forget to update your backup process to back up your PostgreSQL database instead of your MySQL database now.
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
Peer authentication failed
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
Sometimes you might see an error message like this::
|
||||
|
||||
django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "pretix"
|
||||
|
||||
It is important to understand that PostgreSQL by default offers two types of authentication:
|
||||
|
||||
- **Peer authentication**, which works automatically based on the Linux user you are working as. This requires that
|
||||
the connection is made through a local socket (empty ``host=`` in ``pretix.cfg``) and the name of the PostgreSQL user
|
||||
and the Linux user are identical.
|
||||
|
||||
- Typically, you might run into this error if you accidentally execute ``python -m pretix`` commands as root instead
|
||||
of the ``pretix`` user.
|
||||
|
||||
- **Password authentication**, which requires a username and password and works over network connections. To force
|
||||
password authentication instead of peer authentication, set ``host=127.0.0.1`` in ``pretix.cfg``.
|
||||
|
||||
- You can alter the password on a PostgreSQL shell using the command ``ALTER USER pretix WITH PASSWORD '***';``.
|
||||
When creating a user with the ``createuser`` command, pass option ``-P`` to set a new password.
|
||||
|
||||
- Even with password authentication, PostgreSQL by default only allows local connections. To allow remote connections,
|
||||
you need to adjust both the ``listen_address`` configuration parameter as well as the ``pg_hba.conf`` file (see above
|
||||
for an example with the docker networking setup).
|
||||
|
||||
Database error: relation does not exist
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
If you see an error like this::
|
||||
|
||||
2023-04-17T19:20:47.744023Z ERROR Database error 42P01: relation "public.pretix_foobar" does not exist
|
||||
QUERY: ALTER TABLE public.pretix_foobar DROP CONSTRAINT IF EXISTS pretix_foobar_order_id_57e2cb41_fk_pretixbas CASCADE;
|
||||
2023-04-17T19:20:47.744023Z FATAL Failed to create the schema, see above.
|
||||
|
||||
The reason is most likely that in the past, you installed a pretix plugin that you no longer have installed. However,
|
||||
the database still contains tables of that plugin. If you want to keep the data, reinstall the plugin and re-run the
|
||||
``migrate`` step from above. If you want to get rid of the data, manually drop the table mentioned in the error message
|
||||
from your MySQL database::
|
||||
|
||||
# mysql -u root pretix
|
||||
mysql> DROP TABLE pretix_foobar;
|
||||
|
||||
Then, retry. You might see a new error message with a new table, which you can handle the same way.
|
||||
|
||||
Cleaning out a failed attempt
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
You might want to clean your PostgreSQL database before you try again after an error. You can do so like this::
|
||||
|
||||
# sudo -u postgres psql pretix
|
||||
pretix=# DROP SCHEMA public CASCADE;
|
||||
pretix=# CREATE SCHEMA public;
|
||||
pretix=# ALTER SCHEMA public OWNER TO pretix;
|
||||
|
||||
``pgloader`` crashes with heap exhaustion error
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
On some larger databases, we've seen ``pgloader`` crash with error messages similar to this::
|
||||
|
||||
Heap exhausted during garbage collection: 16 bytes available, 48 requested.
|
||||
|
||||
Or this::
|
||||
|
||||
2021-01-04T21:31:17.367000Z ERROR A SB-KERNEL::HEAP-EXHAUSTED-ERROR condition without bindings for heap statistics. (If
|
||||
you did not expect to see this message, please report it.
|
||||
2021-01-04T21:31:17.382000Z ERROR The value
|
||||
NIL
|
||||
is not of type
|
||||
NUMBER
|
||||
when binding SB-KERNEL::X
|
||||
|
||||
The ``pgloader`` version distributed for Debian and Ubuntu is compiled with the ``SBCL`` compiler. If compiled with
|
||||
``CCL``, these bugs go away. Unfortunately, it is pretty hard to compile ``pgloader`` manually with ``CCL``. If you
|
||||
run into this, we therefore recommend using the docker container provided by the ``pgloader`` maintainers::
|
||||
|
||||
sudo docker run --rm -v /tmp:/tmp --network host -it dimitri/pgloader:ccl.latest pgloader /tmp/pretix.load
|
||||
|
||||
As peer authentication is not available from inside the container, this requires you to use password-based authentication
|
||||
in PostgreSQL (see above).
|
||||
|
||||
|
||||
.. _PostgreSQL repositories: https://wiki.postgresql.org/wiki/Apt
|
||||
236
doc/admin/scaling.rst
Normal file
@@ -0,0 +1,236 @@
|
||||
.. _`scaling`:
|
||||
|
||||
Scaling guide
|
||||
=============
|
||||
|
||||
Our :ref:`installation guide <installation>` only covers "small-scale" setups, by which we mostly mean
|
||||
setups that run on a **single (virtual) machine** and do not encounter large traffic peaks.
|
||||
|
||||
We do not offer an installation guide for larger-scale setups of pretix, mostly because we believe that
|
||||
there is no one-size-fits-all solution for this and the desired setup highly depends on your use case,
|
||||
the platform you run pretix on, and your technical capabilities. We do not recommend trying set up pretix
|
||||
in a multi-server environment if you do not already have experience with managing server clusters.
|
||||
|
||||
This document is intended to give you a general idea on what issues you will encounter when you scale up
|
||||
and what you should think of.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you require more help on this, we're happy to help. Our pretix Enterprise support team has built
|
||||
and helped building, scaling and load-testing pretix installations at any scale and we're looking
|
||||
forward to work with you on fine-tuning your system. If you intend to sell **more than a thousand
|
||||
tickets in a very short amount of time**, we highly recommend reaching out and at least talking this
|
||||
through. Just get in touch at sales@pretix.eu!
|
||||
|
||||
Scaling reasons
|
||||
---------------
|
||||
|
||||
There are two main reasons for scaling up a pretix installation beyond a single server:
|
||||
|
||||
* **Availability:** Distributing pretix over multiple servers can allow you to survive failure of one or more single machines, leading to a higher uptime and reliability of your system.
|
||||
|
||||
* **Traffic and throughput:** Distributing pretix over multiple servers can allow you to process more web requests and ticket sales at the same time.
|
||||
|
||||
You are very unlikely to require scaling for other reasons, such as having too much data in your database.
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
A pretix installation usually consists of the following components which run performance-relevant processes:
|
||||
|
||||
* ``pretix-web`` is the Django-based web application that serves all user interaction.
|
||||
|
||||
* ``pretix-worker`` is a Celery-based application that processes tasks that should be run asynchronously outside of the web application process.
|
||||
|
||||
* A **PostgreSQL database** keeps all the important data and processes the actual transactions.
|
||||
|
||||
* A **web server** that terminates TLS and HTTP connections and forwards them to ``pretix-web``. In some cases, e.g. when serving static files, the web servers might return a response directly. We recommend using ``nginx``.
|
||||
|
||||
* A **redis** server responsible for the communication between ``pretix-web`` and ``pretix-worker``, as well as for caching.
|
||||
|
||||
* A directory of **media files** such as user-uploaded files or generated files (tickets, invoices, …) that are created and used by ``pretix-web``, ``pretix-worker`` and the web server.
|
||||
|
||||
In the following, we will discuss the scaling behavior of every component individually. In general, you can run all of the components
|
||||
on the same server, but you can just as well distribute every component to its own server, or even use multiple servers for some single
|
||||
components.
|
||||
|
||||
.. warning::
|
||||
|
||||
When setting up your system, don't forget about security. In a multi-server environment,
|
||||
you need to take special care to ensure that no unauthorized access to your database
|
||||
is possible through the network and that it's not easy to wiretap your connections. We
|
||||
recommend a rigorous use of firewalls and encryption on all communications. You can
|
||||
ensure this either on an application level (such as using the TLS support in your
|
||||
database) or on a network level with a VPN solution.
|
||||
|
||||
Web server
|
||||
""""""""""
|
||||
|
||||
Your web server is at the very front of your installation. It will need to absorb all of the traffic, and it should be able to
|
||||
at least show a decent error message, even when everything else fails. Luckily, web servers are really fast these days, so this
|
||||
can be achieved without too much work.
|
||||
|
||||
We recommend reading up on tuning your web server for high concurrency. For nginx, this means thinking about the number of worker
|
||||
processes and the number of connections each worker process accepts. Double-check that TLS session caching works, because TLS
|
||||
handshakes can get really expensive.
|
||||
|
||||
During a traffic peak, your web server will be able to make use of more CPU resources, while memory usage will stay comparatively low,
|
||||
so if you invest in more hardware here, invest in more and faster CPU cores.
|
||||
|
||||
Make sure that pretix' static files (such as CSS and JavaScript assets) as well as user-uploaded media files (event logos, etc)
|
||||
are served directly by your web server and your web server caches them in-memory (nginx does it by default) and sets useful
|
||||
headers for client-side caching. As an additional performance improvement, you can turn of access logging for these types of files.
|
||||
If you want, you can even farm out serving static files to a different web server entirely and :ref:`configure pretix to reference
|
||||
them from a different URL <config-urls>`.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you expect *really high traffic* for your very popular event, you might want to do some rate limiting on this layer, or,
|
||||
if you want to ensure a fair and robust first-come-first-served experience and prefer letting users wait over showing them
|
||||
errors, consider a queuing solution. We're happy to provide you with such systems, just get in touch at sales@pretix.eu.
|
||||
|
||||
pretix-web
|
||||
""""""""""
|
||||
|
||||
The ``pretix-web`` process does not carry any internal state and can be easily started on as many machines as you like, and you can
|
||||
use the load balancing features of your frontend web server to redirect to all of them.
|
||||
|
||||
You can adjust the number of processes in the ``gunicorn`` command line, and we recommend choosing roughly two times the number
|
||||
of CPU cores available. Under load, the memory consumption of ``pretix-web`` will stay comparatively constant, while the CPU usage
|
||||
will increase a lot. Therefore, if you can add more or faster CPU cores, you will be able to serve more users.
|
||||
|
||||
pretix-worker
|
||||
"""""""""""""
|
||||
|
||||
The ``pretix-worker`` process performs all operations that are not directly executed in the request-response-cycle of ``pretix-web``.
|
||||
Just like ``pretix-web`` you can easily start up as many instances as you want on different machines to share the work. As long as they
|
||||
all talk to the same redis server, they will all receive tasks from ``pretix-web``, work on them and post their result back.
|
||||
You can configure the number of threads that run tasks in parallel through the ``--concurrency`` command line option of ``celery``.
|
||||
|
||||
Just like ``pretix-web``, this process is mostly heavy on CPU, disk IO and network IO, although memory peaks can occur e.g. during the
|
||||
generation of large PDF files, so we recommend having some reserves here.
|
||||
|
||||
``pretix-worker`` performs a variety of tasks which are of different importance.
|
||||
Some of them are mission-critical and need to be run quickly even during high load (such as
|
||||
creating a cart or an order), others are irrelevant and can easily run later (such as
|
||||
distributing tickets on the waiting list). You can fine-tune the capacity you assign to each
|
||||
of these tasks by running ``pretix-worker`` processes that only work on a specific **queue**.
|
||||
For example, you could have three servers dedicated only to process order creations and one
|
||||
server dedicated only to sending emails. This allows you to set priorities and also protects
|
||||
you from e.g. a slow email server lowering your ticket throughput.
|
||||
|
||||
You can do so by specifying one or more queues on the ``celery`` command line of this process, such as ``celery -A pretix.celery_app worker -Q notifications,mail``. Currently,
|
||||
the following queues exist:
|
||||
|
||||
* ``checkout`` -- This queue handles everything related to carts and orders and thereby everything required to process a sale. This includes adding and deleting items from carts as well as creating and canceling orders.
|
||||
|
||||
* ``mail`` -- This queue handles sending of outgoing emails.
|
||||
|
||||
* ``notifications`` -- This queue handles the processing of any outgoing notifications, such as email notifications to admin users (except for the actual sending) or API notifications to registered webhooks.
|
||||
|
||||
* ``background`` -- This queue handles tasks that are expected to take long or have no human waiting for their result immediately, such as refreshing caches, re-generating CSS files, assigning tickets on the waiting list or parsing bank data files.
|
||||
|
||||
* ``default`` -- This queue handles everything else with "medium" or unassigned priority, most prominently the generation of files for tickets, invoices, badges, admin exports, etc.
|
||||
|
||||
Media files
|
||||
"""""""""""
|
||||
|
||||
Both ``pretix-web``, ``pretix-worker`` and in some cases your webserver need to work with
|
||||
media files. Media files are all files generated *at runtime* by the software. This can
|
||||
include files uploaded by the event organizers, such as the event logo, files uploaded by
|
||||
ticket buyers (if you use such features) or files generated by the software, such as
|
||||
ticket files, invoice PDFs, data exports or customized CSS files.
|
||||
|
||||
Those files are by default stored to the ``media/`` sub-folder of the data directory given
|
||||
in the ``pretix.cfg`` configuration file. Inside that ``media/`` folder, you will find a
|
||||
``pub/`` folder containing the subset of files that should be publicly accessible through
|
||||
the web server. Everything else only needs to be accessible by ``pretix-web`` and
|
||||
``pretix-worker`` themselves.
|
||||
|
||||
If you distribute ``pretix-web`` or ``pretix-worker`` across more than one machine, you
|
||||
**must** make sure that they all have access to a shared storage to read and write these
|
||||
files, otherwise you **will** run into errors with the user interface.
|
||||
|
||||
The easiest solution for this is probably to store them on a NFS server that you mount
|
||||
on each of the other servers.
|
||||
|
||||
Since we use Django's file storage mechanism internally, you can in theory also use an object-storage solution like Amazon S3, Ceph, or Minio to store these files, although we currently do not expose this through pretix' configuration file and this would require you to ship your own variant of ``pretix/settings.py`` and reference it through the ``DJANGO_SETTINGS_MODULE`` environment variable.
|
||||
|
||||
At pretix.eu, we use a custom-built `object storage cluster`_.
|
||||
|
||||
SQL database
|
||||
""""""""""""
|
||||
|
||||
One of the most critical parts of the whole setup is the SQL database -- and certainly the
|
||||
hardest to scale. Tuning relational databases is an art form, and while there's lots of
|
||||
material on it on the internet, there's not a single recipe that you can apply to every case.
|
||||
|
||||
As a general rule of thumb, the more resources you can give your databases, the better.
|
||||
Most databases will happily use all CPU cores available, but only use memory up to an amount
|
||||
you configure, so make sure to set this memory usage as high as you can afford. Having more
|
||||
memory available allows your database to make more use of caching, which is usually good.
|
||||
|
||||
Scaling your database to multiple machines needs to be treated with great caution. It's a
|
||||
good idea to have a replica of your database for availability reasons. In case your primary
|
||||
database server fails, you can easily switch over to the replica and continue working.
|
||||
|
||||
However, using database replicas for performance gain is much more complicated. When using
|
||||
replicated database systems, you are always trading in consistency or availability to get
|
||||
additional performance and the consequences of this can be subtle. It is important
|
||||
that you have a deep understanding of the semantics of your replication mechanism.
|
||||
|
||||
.. warning::
|
||||
|
||||
Using an off-the-shelf database proxy solution that redirects read queries to your
|
||||
replicas and write queries to your primary database **will lead to very nasty bugs.**
|
||||
|
||||
As an example, if you buy a ticket, pretix first needs to calculate how many tickets
|
||||
are left to sell. If this calculation is done on a database replica that lags behind
|
||||
even for fractions of a second, the decision to allow selling the ticket will be made
|
||||
on stale data and you can end up with more tickets sold than configured. Similarly,
|
||||
you could imagine situations leading to double payments etc.
|
||||
|
||||
If you do have a replica, you *can* tell pretix about it :ref:`in your configuration <config-replica>`.
|
||||
This way, pretix can offload complex read-only queries to the replica when it is safe to do so.
|
||||
As of pretix 2.7, this is mainly used for search queries in the backend and for rendering the
|
||||
product list and event lists in the frontend, but we plan on expanding this in the future.
|
||||
|
||||
Therefore, for now our clear recommendation is: Try to scale your database vertically and put
|
||||
it on the most powerful machine you have available.
|
||||
|
||||
redis
|
||||
"""""
|
||||
|
||||
While redis is a very important part that glues together some of the components, it isn't used
|
||||
heavily and can usually handle a fairly large pretix installation easily on a single modern
|
||||
CPU core.
|
||||
Having some memory available is good, e.g. if lots of tasks queue up during a traffic peak, but we wouldn't expect ever needing more than a gigabyte of it.
|
||||
|
||||
Feel free to set up a redis cluster for availability – but you probably won't need it for performance.
|
||||
|
||||
The limitations
|
||||
---------------
|
||||
|
||||
Up to a certain point, pretix scales really well. However, there are a few things that we consider
|
||||
even more important than scalability, and those are correctness and reliability. We want you to be
|
||||
able to trust that pretix will not sell more tickets than you intended or run into similar error
|
||||
cases.
|
||||
|
||||
Combined with pretix' flexibility and complexity, especially around vouchers and quotas, this creates
|
||||
some hard issues. In many cases, we need to fall back to event-global locking for some actions which
|
||||
are likely to run with high concurrency and cause harm.
|
||||
|
||||
For every event, only one of these locking actions can be run at the same time. Examples for this are
|
||||
adding products limited by a quota to a cart, adding items to a cart using a voucher or placing an order
|
||||
consisting of cart positions that don't have a valid reservation for much longer. In these cases, it is
|
||||
currently not realistically possible to exceed selling **approx. 500 orders per minute per event**, even
|
||||
if you add more hardware.
|
||||
If you have an unlimited number of tickets, we can apply fewer locking and we've reached **approx.
|
||||
1500 orders per minute per event** in benchmarks, although even more should be possible.
|
||||
|
||||
We're working on reducing the number of cases in which this is relevant and thereby improve the possible
|
||||
throughput. If you want to use pretix for an event with 10,000+ tickets that are likely to be sold out
|
||||
within minutes, please get in touch to discuss possible solutions. We'll work something out for you!
|
||||
|
||||
|
||||
.. _object storage cluster: https://behind.pretix.eu/2018/03/20/high-available-cdn/
|
||||
51
doc/admin/updates.rst
Normal file
@@ -0,0 +1,51 @@
|
||||
.. _`update_notes`:
|
||||
|
||||
Update notes
|
||||
============
|
||||
|
||||
pretix receives regular feature and bugfix updates and we highly encourage you to always update to
|
||||
the latest version for maximum quality and security. Updates are announces on our `blog`_. There are
|
||||
usually 10 feature updates in a year, so you can expect a new release almost every month.
|
||||
|
||||
Pure bugfix releases are only issued in case of very critical bugs or security vulnerabilities. In these
|
||||
case, we'll publish bugfix releases for the last three stable release branches.
|
||||
|
||||
Compatibility to plugins and in very rare cases API clients may break. For in-depth details on the
|
||||
API changes of every version, please refer to the release notes published on our blog.
|
||||
|
||||
Upgrade steps
|
||||
-------------
|
||||
|
||||
For the actual upgrade, you can usually just follow the steps from the installation guide for :ref:`manual installations <manual_updates>`
|
||||
or :ref:`docker installations <docker_updates>` respectively.
|
||||
Generally, it is always strongly recommended to perform a :ref:`backup <backups>` first.
|
||||
It is possible to skip versions during updates, although we recommend not skipping over major version numbers
|
||||
(i.e. if you want to go from 2.4 to 4.4, first upgrade to 3.0, then upgrade to 4.0, then to 4.4).
|
||||
|
||||
In addition to these standard update steps, the following list issues steps that should be taken when you upgrade
|
||||
to specific versions for pretix. If you're skipping versions, please read the instructions for every version in
|
||||
between as well.
|
||||
|
||||
Upgrade to 3.17.0 or newer
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
pretix 3.17 introduces a dependency on ``nodejs``, so you should install it on your system::
|
||||
|
||||
# apt install nodejs npm
|
||||
|
||||
Upgrade to 4.4.0 or newer
|
||||
"""""""""""""""""""""""""
|
||||
|
||||
pretix 4.4 introduces a new data structure to store historical financial data. If you already have existing
|
||||
data in your database, you will need to back-fill this data or you might get incorrect reports! This is not
|
||||
done automatically as part of the usual update steps since it can take a while on large databases and you might
|
||||
want to do it in parallel while the system is already running again. Please execute the following command::
|
||||
|
||||
(venv)$ python -m pretix create_order_transactions
|
||||
|
||||
Or, with a docker installation::
|
||||
|
||||
$ docker exec -it pretix.service pretix create_order_transactions
|
||||
|
||||
|
||||
.. _blog: https://pretix.eu/about/en/blog/
|
||||
@@ -249,10 +249,7 @@ You can get three response codes:
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event": {
|
||||
"name": "Demo Conference",
|
||||
"slug": "democon"
|
||||
},
|
||||
"event": "democon",
|
||||
"subevent": 23,
|
||||
"checkinlist": 5
|
||||
}
|
||||
|
||||
@@ -94,9 +94,7 @@ If you want the user to return to your application after the payment is complete
|
||||
"Plugins". Enable the plugin "Redirection from order page". Then, go to the new page "Settings", then "Redirection".
|
||||
Enter the base URL of your web application. This will allow you to redirect to pages under this base URL later on.
|
||||
For example, if you want users to be redirected to ``https://example.org/order/return?tx_id=1234``, you could now
|
||||
either enter ``https://example.org/order/`` or ``https://example.org/``.
|
||||
Please note that in the latter case the trailing slash is required, ``https://example.org`` is not allowed to prevent.
|
||||
Only base URLs with a secure (``https://``) or local (``http://localhost``) origin are permitted.
|
||||
either enter ``https://example.org`` or ``https://example.org/order/``.
|
||||
|
||||
The user will be redirected back to your page instead of pretix' order confirmation page after the payment,
|
||||
**regardless of whether it was successful or not**. We will append an ``error=…`` query parameter with an error
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
.. _rest-autocheckinrules:
|
||||
|
||||
Auto check-in rules
|
||||
===================
|
||||
|
||||
This feature requires the bundled ``pretix.plugins.autocheckin`` plugin to be active for the event in order to work properly.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Auto check-in rules specify that tickets should under specific conditions automatically be considered checked in after
|
||||
they have been purchased.
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the rule
|
||||
list integer ID of the check-in list to check the ticket in on. If
|
||||
``None``, the system will select all matching check-in lists.
|
||||
mode string ``"placed"`` if the rule should be evaluated right after
|
||||
an order has been created, ``"paid"`` if the rule should
|
||||
be evaluated after the order has been fully paid.
|
||||
all_sales_channels boolean If ``true`` (default), the rule applies to tickets sold on all sales channels.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the rule should apply to
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
all_products boolean If ``true`` (default), the rule affects all products and variations.
|
||||
limit_products list of integers List of item IDs, if ``all_products`` is not set. If the
|
||||
product listed here has variations, all variations will be matched.
|
||||
limit_variations list of integers List of product variation IDs, if ``all_products`` is not set.
|
||||
The parent product does not need to be part of ``limit_products``.
|
||||
all_payment_methods boolean If ``true`` (default), the rule applies to tickets paid with all payment methods.
|
||||
limit_payment_methods list of strings List of payment method identifiers the rule should apply to
|
||||
if ``all_payment_methods`` is ``false``.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionadded:: 2024.7
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/
|
||||
|
||||
Returns a list of all rules configured for an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/ 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,
|
||||
"list": 12345,
|
||||
"mode": "placed",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"all_products": false,
|
||||
"limit_products": [2, 3],
|
||||
"limit_variations": [456],
|
||||
"all_payment_methods": true,
|
||||
"limit_payment_methods": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
|
||||
|
||||
Returns information on one rule, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/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,
|
||||
"list": 12345,
|
||||
"mode": "placed",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"all_products": false,
|
||||
"limit_products": [2, 3],
|
||||
"limit_variations": [456],
|
||||
"all_payment_methods": true,
|
||||
"limit_payment_methods": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the rule to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/
|
||||
|
||||
Create a new rule.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 166
|
||||
|
||||
{
|
||||
"list": 12345,
|
||||
"mode": "placed",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"all_products": false,
|
||||
"limit_products": [2, 3],
|
||||
"limit_variations": [456],
|
||||
"all_payment_methods": true,
|
||||
"limit_payment_methods": []
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"list": 12345,
|
||||
"mode": "placed",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"all_products": false,
|
||||
"limit_products": [2, 3],
|
||||
"limit_variations": [456],
|
||||
"all_payment_methods": true,
|
||||
"limit_payment_methods": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a rule for
|
||||
:param event: The ``slug`` field of the event to create a rule for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The rule could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create rules.
|
||||
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
|
||||
|
||||
Update a rule. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 34
|
||||
|
||||
{
|
||||
"mode": "paid",
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"list": 12345,
|
||||
"mode": "placed",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"all_products": false,
|
||||
"limit_products": [2, 3],
|
||||
"limit_variations": [456],
|
||||
"all_payment_methods": true,
|
||||
"limit_payment_methods": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the rule to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The rule could not be modified due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it.
|
||||
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
|
||||
|
||||
Delete a rule.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the rule to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this rule cannot be deleted since it is currently in use.
|
||||
@@ -40,11 +40,6 @@ answers list of objects Answers to user
|
||||
seat objects The assigned seat (or ``null``)
|
||||
├ id integer Internal ID of the seat instance
|
||||
├ name string Human-readable seat name
|
||||
├ zone_name string Name of the zone the seat is in
|
||||
├ row_name string Name/number of the row the seat is in
|
||||
├ row_label string Additional label of the row (or ``null``)
|
||||
├ seat_number string Number of the seat within the row
|
||||
├ seat_label string Additional label of the seat (or ``null``)
|
||||
└ seat_guid string Identifier of the seat within the seating plan
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -23,22 +23,6 @@ position integer An integer, use
|
||||
is_addon boolean If ``true``, items within this category are not on sale
|
||||
on their own but the category provides a source for
|
||||
defining add-ons for other products.
|
||||
cross_selling_mode string If ``null``, cross-selling is disabled for this category.
|
||||
If ``"only"``, it is only visible in the cross-selling
|
||||
step.
|
||||
If ``"both"``, it is visible on the normal index page
|
||||
as well.
|
||||
Only available if ``is_addon`` is ``false``.
|
||||
cross_selling_condition string Only relevant if ``cross_selling_mode`` is not ``null``.
|
||||
If ``"always"``, always show in cross-selling step.
|
||||
If ``"products"``, only show if the cart contains one of
|
||||
the products listed in ``cross_selling_match_products``.
|
||||
If ``"discounts"``, only show products that qualify for
|
||||
a discount according to discount rules.
|
||||
cross_selling_match_products list of integer Only relevant if ``cross_selling_condition`` is
|
||||
``"products"``. Internal ID of the items of which at
|
||||
least one needs to be in the cart for this category to
|
||||
be shown.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -76,10 +60,7 @@ Endpoints
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false,
|
||||
"cross_selling_mode": null,
|
||||
"cross_selling_condition": null,
|
||||
"cross_selling_match_products": []
|
||||
"is_addon": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -121,10 +102,7 @@ Endpoints
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false,
|
||||
"cross_selling_mode": null,
|
||||
"cross_selling_condition": null,
|
||||
"cross_selling_match_products": []
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -152,10 +130,7 @@ Endpoints
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false,
|
||||
"cross_selling_mode": null,
|
||||
"cross_selling_condition": null,
|
||||
"cross_selling_match_products": []
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -172,10 +147,7 @@ Endpoints
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false,
|
||||
"cross_selling_mode": null,
|
||||
"cross_selling_condition": null,
|
||||
"cross_selling_match_products": []
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create a category for
|
||||
@@ -221,10 +193,7 @@ Endpoints
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": true,
|
||||
"cross_selling_mode": null,
|
||||
"cross_selling_condition": null,
|
||||
"cross_selling_match_products": []
|
||||
"is_addon": true
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
|
||||
@@ -31,7 +31,6 @@ Checking a ticket in
|
||||
This endpoint supports passing multiple check-in lists to perform a multi-event scan. However, each check-in list
|
||||
passed needs to be from a distinct event.
|
||||
|
||||
:query string expand: Expand a field inside the ``position`` object into a full object. Currently ``subevent``, ``item``, ``variation``, and ``answers.question`` are supported. Can be passed multiple times.
|
||||
:<json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
|
||||
:<json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
|
||||
:<json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
|
||||
@@ -64,7 +63,6 @@ Checking a ticket in
|
||||
``checkin_attention`` flag set. (3) If ``attendee_name`` is empty, it may automatically fall
|
||||
back to values from a parent product or from invoice addresses.
|
||||
:>json boolean require_attention: Whether or not the ``require_attention`` flag is set on the item or order.
|
||||
:>json list checkin_texts: List of additional texts to show to the user.
|
||||
:>json object list: Excerpt of information about the matching :ref:`check-in list <rest-checkinlists>` (if any was found),
|
||||
including the attributes ``id``, ``name``, ``event``, ``subevent``, and ``include_pending``.
|
||||
:>json object questions: List of questions to be answered for check-in, only set on status ``"incomplete"``.
|
||||
@@ -105,7 +103,6 @@ Checking a ticket in
|
||||
…
|
||||
},
|
||||
"require_attention": false,
|
||||
"checkin_texts": [],
|
||||
"list": {
|
||||
"id": 1,
|
||||
"name": "Default check-in list",
|
||||
@@ -128,7 +125,6 @@ Checking a ticket in
|
||||
…
|
||||
},
|
||||
"require_attention": false,
|
||||
"checkin_texts": [],
|
||||
"list": {
|
||||
"id": 1,
|
||||
"name": "Default check-in list",
|
||||
@@ -146,7 +142,6 @@ Checking a ticket in
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": true,
|
||||
"show_during_checkin": true,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
@@ -183,8 +178,7 @@ Checking a ticket in
|
||||
"status": "error",
|
||||
"reason": "invalid",
|
||||
"reason_explanation": null,
|
||||
"require_attention": false,
|
||||
"checkin_texts": []
|
||||
"require_attention": false
|
||||
}
|
||||
|
||||
**Example error response (known, but invalid ticket)**:
|
||||
@@ -199,7 +193,6 @@ Checking a ticket in
|
||||
"reason": "unpaid",
|
||||
"reason_explanation": null,
|
||||
"require_attention": false,
|
||||
"checkin_texts": [],
|
||||
"list": {
|
||||
"id": 1,
|
||||
"name": "Default check-in list",
|
||||
@@ -224,7 +217,6 @@ Checking a ticket in
|
||||
* ``rules`` - Check-in prevented by a user-defined rule.
|
||||
* ``ambiguous`` - Multiple tickets match scan, rejected.
|
||||
* ``revoked`` - Ticket code has been revoked.
|
||||
* ``unapproved`` - Order has not yet been approved.
|
||||
* ``error`` - Internal error.
|
||||
|
||||
In case of reason ``rules`` and ``invalid_time``, there might be an additional response field ``reason_explanation``
|
||||
|
||||
@@ -31,23 +31,18 @@ subevent integer ID of the date
|
||||
position_count integer Number of tickets that match this list (read-only).
|
||||
checkin_count integer Number of check-ins performed on this list (read-only).
|
||||
include_pending boolean If ``true``, the check-in list also contains tickets from orders in pending state.
|
||||
auto_checkin_sales_channels list of strings All items on the check-in list will be automatically marked as checked-in when purchased through any of the listed sales channels.
|
||||
allow_multiple_entries boolean If ``true``, subsequent scans of a ticket on this list should not show a warning but instead be stored as an additional check-in.
|
||||
allow_entry_after_exit boolean If ``true``, subsequent scans of a ticket on this list are valid if the last scan of the ticket was an exit scan.
|
||||
rules object Custom check-in logic. The contents of this field are currently not considered a stable API and modifications through the API are highly discouraged.
|
||||
exit_all_at datetime Automatically check out (i.e. perform an exit scan) at this point in time. After this happened, this property will automatically be set exactly one day into the future. Note that this field is considered "internal configuration" and if you pull the list with ``If-Modified-Since``, the daily change in this field will not trigger a response.
|
||||
addon_match boolean If ``true``, tickets on this list can be redeemed by scanning their parent ticket if this still leads to an unambiguous match.
|
||||
ignore_in_statistics boolean If ``true``, check-ins on this list will be ignored in most reporting features.
|
||||
consider_tickets_used boolean If ``true`` (default), tickets checked in on this list will be considered "used" by other functionality, i.e. when checking if they can still be canceled.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 4.12
|
||||
|
||||
The ``addon_match`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2023.9
|
||||
|
||||
The ``ignore_in_statistics`` and ``consider_tickets_used`` attributes have been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -89,7 +84,10 @@ Endpoints
|
||||
"allow_entry_after_exit": true,
|
||||
"exit_all_at": null,
|
||||
"rules": {},
|
||||
"addon_match": false
|
||||
"addon_match": false,
|
||||
"auto_checkin_sales_channels": [
|
||||
"pretixpos"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -141,7 +139,10 @@ Endpoints
|
||||
"allow_entry_after_exit": true,
|
||||
"exit_all_at": null,
|
||||
"rules": {},
|
||||
"addon_match": false
|
||||
"addon_match": false,
|
||||
"auto_checkin_sales_channels": [
|
||||
"pretixpos"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -238,7 +239,10 @@ Endpoints
|
||||
"subevent": null,
|
||||
"allow_multiple_entries": false,
|
||||
"allow_entry_after_exit": true,
|
||||
"addon_match": false
|
||||
"addon_match": false,
|
||||
"auto_checkin_sales_channels": [
|
||||
"pretixpos"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -260,7 +264,10 @@ Endpoints
|
||||
"subevent": null,
|
||||
"allow_multiple_entries": false,
|
||||
"allow_entry_after_exit": true,
|
||||
"addon_match": false
|
||||
"addon_match": false,
|
||||
"auto_checkin_sales_channels": [
|
||||
"pretixpos"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a list for
|
||||
@@ -312,7 +319,10 @@ Endpoints
|
||||
"subevent": null,
|
||||
"allow_multiple_entries": false,
|
||||
"allow_entry_after_exit": true,
|
||||
"addon_match": false
|
||||
"addon_match": false,
|
||||
"auto_checkin_sales_channels": [
|
||||
"pretixpos"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
@@ -325,7 +335,7 @@ Endpoints
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/checkinlist/(id)/
|
||||
|
||||
Delete a check-in list. **Note that this also deletes the information on all check-ins performed via this list.**
|
||||
Delete a check-in list. Note that this also deletes the information on all check-ins performed via this list.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -482,7 +492,7 @@ Order position endpoints
|
||||
``attendee_name,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query string search: Fuzzy search matching the attendee name, order code, invoice address name as well as to the beginning of the secret.
|
||||
:query string expand: Expand a field into a full object. Currently ``subevent``, ``item``, ``variation``, and ``answers.question`` are supported. Can be passed multiple times.
|
||||
:query string expand: Expand a field into a full object. Currently only ``subevent``, ``item``, and ``variation`` are supported. Can be passed multiple times.
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
@@ -616,8 +626,7 @@ Order position endpoints
|
||||
set this to ``false``. In that case, questions will just be ignored. Defaults
|
||||
to ``true``.
|
||||
:<json boolean canceled_supported: When this parameter is set to ``true``, the response code ``canceled`` may be
|
||||
returned. Otherwise, canceled orders will return ``unpaid``. (**Deprecated**, in
|
||||
the future, this will be ignored and ``canceled`` may always be returned.)
|
||||
returned. Otherwise, canceled orders will return ``unpaid``.
|
||||
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
|
||||
questions that have not been filled. This is usually used to upload offline scans that already happened,
|
||||
@@ -691,7 +700,6 @@ Order position endpoints
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": true,
|
||||
"show_during_checkin": true,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
@@ -744,7 +752,6 @@ Order position endpoints
|
||||
* ``rules`` - Check-in prevented by a user-defined rule.
|
||||
* ``ambiguous`` - Multiple tickets match scan, rejected.
|
||||
* ``revoked`` - Ticket code has been revoked.
|
||||
* ``unapproved`` - Order has not yet been approved.
|
||||
|
||||
In case of reason ``rules`` or ``invalid_time``, there might be an additional response field ``reason_explanation``
|
||||
with a human-readable description of the violated rules. However, that field can also be missing or be ``null``.
|
||||
@@ -760,4 +767,4 @@ Order position endpoints
|
||||
:statuscode 404: The requested order position or check-in list does not exist.
|
||||
|
||||
|
||||
.. _security issues: https://pretix.eu/about/de/blog/20220705-release-4111/
|
||||
.. _security issues: https://pretix.eu/about/de/blog/20220705-release-4111/
|
||||
@@ -19,7 +19,6 @@ external_identifier string External ID of
|
||||
the API, but is read-only for customers created through a
|
||||
SSO integration.
|
||||
email string Customer email address
|
||||
phone string Customer phone number
|
||||
name string Name of this customer (or ``null``)
|
||||
name_parts object of strings Decomposition of name (i.e. given name, family name)
|
||||
is_active boolean Whether this account is active
|
||||
@@ -40,10 +39,6 @@ password string Can only be set
|
||||
|
||||
Passwords can now be set through the API during customer creation.
|
||||
|
||||
.. versionchanged:: 2024.3
|
||||
|
||||
The attribute ``phone`` has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -76,7 +71,6 @@ Endpoints
|
||||
"identifier": "8WSAJCJ",
|
||||
"external_identifier": null,
|
||||
"email": "customer@example.org",
|
||||
"phone": "+493012345678",
|
||||
"name": "John Doe",
|
||||
"name_parts": {
|
||||
"_scheme": "full",
|
||||
@@ -124,7 +118,6 @@ Endpoints
|
||||
"identifier": "8WSAJCJ",
|
||||
"external_identifier": null,
|
||||
"email": "customer@example.org",
|
||||
"phone": "+493012345678",
|
||||
"name": "John Doe",
|
||||
"name_parts": {
|
||||
"_scheme": "full",
|
||||
@@ -162,7 +155,6 @@ Endpoints
|
||||
|
||||
{
|
||||
"email": "test@example.org",
|
||||
"phone": "+493012345678",
|
||||
"password": "verysecret",
|
||||
"send_email": true
|
||||
}
|
||||
@@ -179,7 +171,6 @@ Endpoints
|
||||
"identifier": "8WSAJCJ",
|
||||
"external_identifier": null,
|
||||
"email": "test@example.org",
|
||||
"phone": "+493012345678",
|
||||
...
|
||||
}
|
||||
|
||||
@@ -224,7 +215,6 @@ Endpoints
|
||||
"identifier": "8WSAJCJ",
|
||||
"external_identifier": null,
|
||||
"email": "test@example.org",
|
||||
"phone": "+493012345678",
|
||||
…
|
||||
}
|
||||
|
||||
@@ -259,7 +249,6 @@ Endpoints
|
||||
"identifier": "8WSAJCJ",
|
||||
"external_identifier": null,
|
||||
"email": null,
|
||||
"phone": null,
|
||||
…
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,8 @@ id integer Internal ID
|
||||
active boolean The discount will be ignored if this is ``false``
|
||||
internal_name string A name for the rule used in the backend
|
||||
position integer An integer, used for sorting the rules which are applied in order
|
||||
all_sales_channels boolean If ``true`` (default), the discount is available on all sales channels
|
||||
that support discounts.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the discount is available on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
|
||||
and ``limit_sales_channels`` instead.
|
||||
sales_channels list of strings Sales channels this discount is available on, such as
|
||||
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
|
||||
available_from datetime The first date time at which this discount can be applied
|
||||
(or ``null``).
|
||||
available_until datetime The last date time at which this discount can be applied
|
||||
@@ -35,9 +31,9 @@ subevent_mode strings Determines h
|
||||
``"same"`` (discount is only applied for groups within
|
||||
the same date), or ``"distinct"`` (discount is only applied
|
||||
for groups with no two same dates).
|
||||
condition_all_products boolean If ``true``, the discount condition applies to all items.
|
||||
condition_all_products boolean If ``true``, the discount applies to all items.
|
||||
condition_limit_products list of integers If ``condition_all_products`` is not set, this is a list
|
||||
of internal item IDs that the discount condition applies to.
|
||||
of internal item IDs that the discount applies to.
|
||||
condition_apply_to_addons boolean If ``true``, the discount applies to add-on products as well,
|
||||
otherwise it only applies to top-level items. The discount never
|
||||
applies to bundled products.
|
||||
@@ -52,17 +48,6 @@ benefit_discount_matching_percent decimal (string) The percenta
|
||||
benefit_only_apply_to_cheapest_n_matches integer If set higher than 0, the discount will only be applied to
|
||||
the cheapest matches. Useful for a "3 for 2"-style discount.
|
||||
Cannot be combined with ``condition_min_value``.
|
||||
benefit_same_products boolean If ``true``, the discount benefit applies to the same set of items
|
||||
as the condition (see above).
|
||||
benefit_limit_products list of integers If ``benefit_same_products`` is not set, this is a list
|
||||
of internal item IDs that the discount benefit applies to.
|
||||
benefit_apply_to_addons boolean (Only used if ``benefit_same_products`` is ``false``.)
|
||||
If ``true``, the discount applies to add-on products as well,
|
||||
otherwise it only applies to top-level items. The discount never
|
||||
applies to bundled products.
|
||||
benefit_ignore_voucher_discounted boolean (Only used if ``benefit_same_products`` is ``false``.)
|
||||
If ``true``, the discount does not apply to products which have
|
||||
been discounted by a voucher.
|
||||
======================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -99,8 +84,6 @@ Endpoints
|
||||
"active": true,
|
||||
"internal_name": "3 for 2",
|
||||
"position": 1,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
@@ -111,10 +94,6 @@ Endpoints
|
||||
"condition_ignore_voucher_discounted": false,
|
||||
"condition_min_count": 3,
|
||||
"condition_min_value": "0.00",
|
||||
"benefit_same_products": true,
|
||||
"benefit_limit_products": [],
|
||||
"benefit_apply_to_addons": true,
|
||||
"benefit_ignore_voucher_discounted": false,
|
||||
"benefit_discount_matching_percent": "100.00",
|
||||
"benefit_only_apply_to_cheapest_n_matches": 1
|
||||
}
|
||||
@@ -157,8 +136,6 @@ Endpoints
|
||||
"active": true,
|
||||
"internal_name": "3 for 2",
|
||||
"position": 1,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
@@ -169,10 +146,6 @@ Endpoints
|
||||
"condition_ignore_voucher_discounted": false,
|
||||
"condition_min_count": 3,
|
||||
"condition_min_value": "0.00",
|
||||
"benefit_same_products": true,
|
||||
"benefit_limit_products": [],
|
||||
"benefit_apply_to_addons": true,
|
||||
"benefit_ignore_voucher_discounted": false,
|
||||
"benefit_discount_matching_percent": "100.00",
|
||||
"benefit_only_apply_to_cheapest_n_matches": 1
|
||||
}
|
||||
@@ -201,8 +174,6 @@ Endpoints
|
||||
"active": true,
|
||||
"internal_name": "3 for 2",
|
||||
"position": 1,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
@@ -213,10 +184,6 @@ Endpoints
|
||||
"condition_ignore_voucher_discounted": false,
|
||||
"condition_min_count": 3,
|
||||
"condition_min_value": "0.00",
|
||||
"benefit_same_products": true,
|
||||
"benefit_limit_products": [],
|
||||
"benefit_apply_to_addons": true,
|
||||
"benefit_ignore_voucher_discounted": false,
|
||||
"benefit_discount_matching_percent": "100.00",
|
||||
"benefit_only_apply_to_cheapest_n_matches": 1
|
||||
}
|
||||
@@ -234,8 +201,6 @@ Endpoints
|
||||
"active": true,
|
||||
"internal_name": "3 for 2",
|
||||
"position": 1,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
@@ -246,10 +211,6 @@ Endpoints
|
||||
"condition_ignore_voucher_discounted": false,
|
||||
"condition_min_count": 3,
|
||||
"condition_min_value": "0.00",
|
||||
"benefit_same_products": true,
|
||||
"benefit_limit_products": [],
|
||||
"benefit_apply_to_addons": true,
|
||||
"benefit_ignore_voucher_discounted": false,
|
||||
"benefit_discount_matching_percent": "100.00",
|
||||
"benefit_only_apply_to_cheapest_n_matches": 1
|
||||
}
|
||||
@@ -296,8 +257,6 @@ Endpoints
|
||||
"active": false,
|
||||
"internal_name": "3 for 2",
|
||||
"position": 1,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
@@ -308,10 +267,6 @@ Endpoints
|
||||
"condition_ignore_voucher_discounted": false,
|
||||
"condition_min_count": 3,
|
||||
"condition_min_value": "0.00",
|
||||
"benefit_same_products": true,
|
||||
"benefit_limit_products": [],
|
||||
"benefit_apply_to_addons": true,
|
||||
"benefit_ignore_voucher_discounted": false,
|
||||
"benefit_discount_matching_percent": "100.00",
|
||||
"benefit_only_apply_to_cheapest_n_matches": 1
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ geo_lon float Longitude of th
|
||||
has_subevents boolean ``true`` if the event series feature is active for this
|
||||
event. Cannot change after event is created.
|
||||
meta_data object Values set for organizer-specific meta data parameters.
|
||||
The allowed keys need to be set up as meta properties
|
||||
in the organizer configuration.
|
||||
plugins list A list of package names of the enabled plugins for this
|
||||
event.
|
||||
seating_plan integer If reserved seating is in use, the ID of a seating
|
||||
@@ -49,11 +47,8 @@ item_meta_properties object Item-specific m
|
||||
valid_keys object Cryptographic keys for non-default signature schemes.
|
||||
For performance reason, value is omitted in lists and
|
||||
only contained in detail views. Value can be cached.
|
||||
all_sales_channels boolean If ``true`` (default), the event is available on all sales channels.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the event is available on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
|
||||
and ``limit_sales_channels`` instead.
|
||||
sales_channels list A list of sales channels this event is available for
|
||||
sale on.
|
||||
public_url string The public, customer-facing URL of the event (read-only).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
@@ -134,13 +129,11 @@ Endpoints
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.ticketoutputpdf"
|
||||
],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": [
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
],
|
||||
"sales_channels": [],
|
||||
"public_url": "https://pretix.eu/bigevents/sampleconf/"
|
||||
}
|
||||
]
|
||||
@@ -230,8 +223,6 @@ Endpoints
|
||||
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQTdBRDcvdkZBMzNFc1k0ejJQSHI3aVpQc1o4bjVkaDBhalA4Z3l6Tm1tSXM9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
|
||||
]
|
||||
},
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
@@ -289,8 +280,11 @@ Endpoints
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": []
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -326,8 +320,6 @@ Endpoints
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
@@ -351,8 +343,8 @@ Endpoints
|
||||
Creates a new event with properties as set in the request body. The properties that are copied are: ``is_public``,
|
||||
``testmode``, ``has_subevents``, settings, plugin settings, items, variations, add-ons, quotas, categories, tax rules, questions.
|
||||
|
||||
If the ``plugins``, ``has_subevents``, ``meta_data`` and/or ``is_public`` fields are present in the post body this will
|
||||
determine their value. Otherwise their value will be copied from the existing event.
|
||||
If the ``plugins``, ``has_subevents`` and/or ``is_public`` fields are present in the post body this will determine their
|
||||
value. Otherwise their value will be copied from the existing event.
|
||||
|
||||
Please note that you can only copy from events under the same organizer this way. Use the ``clone_from`` parameter
|
||||
when creating a new event for this instead.
|
||||
@@ -393,8 +385,11 @@ Endpoints
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": []
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -430,8 +425,6 @@ Endpoints
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
@@ -507,8 +500,6 @@ Endpoints
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.pretixdroid"
|
||||
],
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
@@ -574,8 +565,6 @@ organizer level.
|
||||
.. warning:: This API is intended for advanced users. Even though we take care to validate your input, you will be
|
||||
able to break your event using this API by creating situations of conflicting settings. Please take care.
|
||||
|
||||
.. note:: When authenticating with :ref:`rest-deviceauth`, only a limited subset of settings is available.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/settings/
|
||||
|
||||
Get current values of event settings.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.. spelling:word-list:: checkin
|
||||
|
||||
.. _rest-exporters:
|
||||
|
||||
Data exporters
|
||||
==============
|
||||
|
||||
|
||||
@@ -96,8 +96,6 @@ Endpoints
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string secret: Only show gift cards with the given secret.
|
||||
:query string value: Only show gift cards with the given value.
|
||||
:query boolean expired: Filter for gift cards that are (not) expired.
|
||||
:query boolean testmode: Filter for gift cards that are (not) in test mode.
|
||||
:query boolean include_accepted: Also show gift cards issued by other organizers that are accepted by this organizer.
|
||||
:query string expand: If you pass ``"owner_ticket"``, the respective field will be shown as a nested value instead of just an ID.
|
||||
|
||||
@@ -22,7 +22,6 @@ at :ref:`plugin-docs`.
|
||||
questions
|
||||
question_options
|
||||
quotas
|
||||
seats
|
||||
orders
|
||||
invoices
|
||||
vouchers
|
||||
@@ -31,7 +30,6 @@ at :ref:`plugin-docs`.
|
||||
checkinlists
|
||||
waitinglist
|
||||
customers
|
||||
saleschannels
|
||||
membershiptypes
|
||||
memberships
|
||||
giftcards
|
||||
@@ -42,18 +40,7 @@ at :ref:`plugin-docs`.
|
||||
webhooks
|
||||
seatingplans
|
||||
exporters
|
||||
scheduled_exports
|
||||
shredders
|
||||
banktransfer
|
||||
ticketoutputpdf
|
||||
badges
|
||||
sendmail_rules
|
||||
auto_checkin_rules
|
||||
campaigns
|
||||
certificates
|
||||
digital
|
||||
exhibitors
|
||||
imported_secrets
|
||||
shipping
|
||||
billing_invoices
|
||||
billing_var
|
||||
billing_var
|
||||
@@ -12,7 +12,6 @@ The invoice resource contains the following public fields:
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
number string Invoice number (with prefix)
|
||||
event string The slug of the parent event
|
||||
order string Order code of the order this invoice belongs to
|
||||
is_cancellation boolean ``true``, if this invoice is the cancellation of a
|
||||
different invoice.
|
||||
@@ -97,7 +96,6 @@ lines list of objects The actual invo
|
||||
├ gross_value money (string) Price including taxes
|
||||
├ tax_value money (string) Tax amount included
|
||||
├ tax_name string Name of used tax rate (e.g. "VAT")
|
||||
├ tax_code string Codified reason for tax rate (or ``null``), see :ref:`rest-taxcodes`.
|
||||
└ tax_rate decimal (string) Used tax rate
|
||||
foreign_currency_display string If the invoice should also show the total and tax
|
||||
amount in a different currency, this contains the
|
||||
@@ -123,17 +121,9 @@ internal_reference string Customer's refe
|
||||
|
||||
The attribute ``lines.subevent`` has been added.
|
||||
|
||||
.. versionchanged:: 2023.8
|
||||
|
||||
The ``event`` attribute has been added. The organizer-level endpoint has been added.
|
||||
|
||||
.. versionchanged:: 2024.8
|
||||
|
||||
The ``tax_code`` attribute has been added.
|
||||
|
||||
|
||||
List of all invoices
|
||||
--------------------
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/
|
||||
|
||||
@@ -162,7 +152,6 @@ List of all invoices
|
||||
"results": [
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"event": "sampleconf",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from_name": "Big Events LLC",
|
||||
@@ -208,7 +197,6 @@ List of all invoices
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_name": "VAT",
|
||||
"tax_code": "S/standard",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
],
|
||||
@@ -223,9 +211,6 @@ List of all invoices
|
||||
:query boolean is_cancellation: If set to ``true`` or ``false``, only invoices with this value for the field
|
||||
``is_cancellation`` will be returned.
|
||||
:query string order: If set, only invoices belonging to the order with the given order code will be returned.
|
||||
This parameter may be given multiple times. In this case, all invoices matching one of the inputs will be returned.
|
||||
:query string number: If set, only invoices with the given invoice number will be returned.
|
||||
This parameter may be given multiple times. In this case, all invoices matching one of the inputs will be returned.
|
||||
:query string refers: If set, only invoices referring to the given invoice will be returned.
|
||||
:query string locale: If set, only invoices with the given locale will be returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date`` and
|
||||
@@ -236,50 +221,6 @@ List of all invoices
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/invoices/
|
||||
|
||||
Returns a list of all invoices within all events of a given organizer (with sufficient access permissions).
|
||||
|
||||
Supported query parameters and output format of this endpoint are identical to the list endpoint within an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/ 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": [
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"event": "sampleconf",
|
||||
"order": "ABC12",
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
|
||||
Fetching individual invoices
|
||||
----------------------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/
|
||||
|
||||
Returns information on one invoice, identified by its invoice number.
|
||||
@@ -302,7 +243,6 @@ Fetching individual invoices
|
||||
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"event": "sampleconf",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from_name": "Big Events LLC",
|
||||
@@ -348,7 +288,6 @@ Fetching individual invoices
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_name": "VAT",
|
||||
"tax_code": "S/standard",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
],
|
||||
@@ -359,12 +298,12 @@ Fetching individual invoices
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param number: The ``number`` field of the invoice to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/download/
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/download/
|
||||
|
||||
Download an invoice in PDF format.
|
||||
|
||||
@@ -391,20 +330,14 @@ Fetching individual invoices
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param number: The ``number`` field of the invoice to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting for a few
|
||||
seconds.
|
||||
|
||||
|
||||
Modifying invoices
|
||||
------------------
|
||||
|
||||
Invoices cannot be edited directly, but the following actions can be triggered:
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/reissue/
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/reissue/
|
||||
|
||||
Cancels the invoice and creates a new one.
|
||||
|
||||
@@ -426,13 +359,13 @@ Invoices cannot be edited directly, but the following actions can be triggered:
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param number: The ``number`` field of the invoice to reissue
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to reissue
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The invoice has already been canceled
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/regenerate/
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/regenerate/
|
||||
|
||||
Re-generates the invoice from order data.
|
||||
|
||||
@@ -454,7 +387,7 @@ Invoices cannot be edited directly, but the following actions can be triggered:
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param number: The ``number`` field of the invoice to regenerate
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to regenerate
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The invoice has already been canceled
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
@@ -18,8 +18,6 @@ default_price money (string) The price set d
|
||||
price money (string) The price used for this variation. This is either the
|
||||
same as ``default_price`` if that value is set or equal
|
||||
to the item's ``default_price`` (read-only).
|
||||
free_price_suggestion money (string) A suggested price, used as a default value if
|
||||
``Item.free_price`` is set (or ``null``).
|
||||
original_price money (string) An original price, shown for comparison, not used
|
||||
for price calculations (or ``null``).
|
||||
active boolean If ``false``, this variation will not be sold or shown.
|
||||
@@ -29,8 +27,6 @@ position integer An integer, use
|
||||
checkin_attention boolean If ``true``, the check-in app should show a warning
|
||||
that this ticket requires special attention if such
|
||||
a variation is being scanned.
|
||||
checkin_text string Text that will be shown if a ticket of this type is
|
||||
scanned (or ``null``).
|
||||
require_approval boolean If ``true``, orders with this variation will need to be
|
||||
approved by the event organizer before they can be
|
||||
paid.
|
||||
@@ -38,26 +34,15 @@ require_membership boolean If ``true``, bo
|
||||
require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this variation will
|
||||
be hidden from users without a valid membership.
|
||||
require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
|
||||
all_sales_channels boolean If ``true`` (default), the variation is available on all sales channels.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the variation is available on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
sales_channels list of strings Sales channels this variation is available on, such as
|
||||
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
|
||||
The item-level list takes precedence, i.e. a sales
|
||||
channel needs to be on both lists for the variation to be
|
||||
available (unless ``all_sales_channels`` is used).
|
||||
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
|
||||
and ``limit_sales_channels`` instead.
|
||||
channel needs to be on both lists for the item to be
|
||||
available.
|
||||
available_from datetime The first date time at which this variation can be bought
|
||||
(or ``null``).
|
||||
available_from_mode string If ``hide`` (the default), this variation is hidden in the shop
|
||||
if unavailable due to the available_from setting.
|
||||
If ``info``, the variation is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
available_until datetime The last date time at which this variation can be bought
|
||||
(or ``null``).
|
||||
available_until_mode string If ``hide`` (the default), this variation is hidden in the shop
|
||||
if unavailable due to the available_until setting.
|
||||
If ``info``, the variation is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
hide_without_voucher boolean If ``true``, this variation is only shown during the voucher
|
||||
redemption process, but not in the normal shop
|
||||
frontend.
|
||||
@@ -68,12 +53,6 @@ meta_data object Values set for
|
||||
|
||||
The ``meta_data`` and ``checkin_attention`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 2023.10
|
||||
|
||||
The ``free_price_suggestion`` attribute has been added.
|
||||
The ``checkin_text`` attribute has been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -109,18 +88,13 @@ Endpoints
|
||||
},
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": {
|
||||
"en": "Test2"
|
||||
@@ -129,7 +103,6 @@ Endpoints
|
||||
"default_price": "223.00",
|
||||
"price": 223.0,
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"meta_data": {}
|
||||
},
|
||||
{
|
||||
@@ -139,32 +112,20 @@ Endpoints
|
||||
},
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": {},
|
||||
"position": 1,
|
||||
"default_price": "223.00",
|
||||
"price": 223.0,
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"default_price": null,
|
||||
"price": 15.0,
|
||||
"meta_data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string search: Filter the list by the value of the variation (substring search).
|
||||
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
|
||||
returned.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -202,21 +163,15 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"position": 0,
|
||||
@@ -249,17 +204,13 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"position": 0,
|
||||
@@ -280,21 +231,15 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"position": 0,
|
||||
@@ -346,21 +291,15 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": false,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_hidden": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"position": 1,
|
||||
|
||||
@@ -29,8 +29,6 @@ free_price boolean If ``true``,
|
||||
they buy the product (however, the price can't be set
|
||||
lower than the price defined by ``default_price`` or
|
||||
otherwise).
|
||||
free_price_suggestion money (string) A suggested price, used as a default value if
|
||||
``free_price`` is set (or ``null``).
|
||||
tax_rate decimal (string) The VAT rate to be applied for this item (read-only,
|
||||
set through ``tax_rule``).
|
||||
tax_rule integer The internal ID of the applied tax rule (or ``null``).
|
||||
@@ -46,33 +44,15 @@ personalized boolean ``true`` for
|
||||
position integer An integer, used for sorting
|
||||
picture file A product picture to be displayed in the shop
|
||||
(can be ``null``).
|
||||
all_sales_channels boolean If ``true`` (default), the item is available on all sales channels.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the item is available on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
|
||||
and ``limit_sales_channels`` instead.
|
||||
sales_channels list of strings Sales channels this product is available on, such as
|
||||
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
|
||||
available_from datetime The first date time at which this item can be bought
|
||||
(or ``null``).
|
||||
available_from_mode string If ``hide`` (the default), this item is hidden in the shop
|
||||
if unavailable due to the ``available_from`` setting.
|
||||
If ``info``, the item is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
available_until datetime The last date time at which this item can be bought
|
||||
(or ``null``).
|
||||
available_until_mode string If ``hide`` (the default), this item is hidden in the shop
|
||||
if unavailable due to the ``available_until`` setting.
|
||||
If ``info``, the item is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
hidden_if_available integer **DEPRECATED** The internal ID of a quota object, or ``null``. If
|
||||
hidden_if_available integer The internal ID of a quota object, or ``null``. If
|
||||
set, this item won't be shown publicly as long as this
|
||||
quota is available.
|
||||
hidden_if_item_available integer The internal ID of a different item, or ``null``. If
|
||||
set, this item won't be shown publicly as long as this
|
||||
other item is available.
|
||||
hidden_if_item_available_mode string If ``hide`` (the default), this item is hidden in the shop
|
||||
if unavailable due to the ``hidden_if_item_available`` setting.
|
||||
If ``info``, the item is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
require_voucher boolean If ``true``, this item can only be bought using a
|
||||
voucher that is specifically assigned to this item.
|
||||
hide_without_voucher boolean If ``true``, this item is only shown during the voucher
|
||||
@@ -89,8 +69,6 @@ max_per_order integer This product
|
||||
checkin_attention boolean If ``true``, the check-in app should show a warning
|
||||
that this ticket requires special attention if such
|
||||
a product is being scanned.
|
||||
checkin_text string Text that will be shown if a ticket of this type is
|
||||
scanned (or ``null``).
|
||||
original_price money (string) An original price, shown for comparison, not used
|
||||
for price calculations (or ``null``).
|
||||
require_approval boolean If ``true``, orders with this product will need to be
|
||||
@@ -145,8 +123,6 @@ variations list of objects A list with o
|
||||
├ price money (string) The price used for this variation. This is either the
|
||||
same as ``default_price`` if that value is set or equal
|
||||
to the item's ``default_price``.
|
||||
├ free_price_suggestion money (string) A suggested price, used as a default value if
|
||||
``free_price`` is set (or ``null``).
|
||||
├ original_price money (string) An original price, shown for comparison, not used
|
||||
for price calculations (or ``null``).
|
||||
├ active boolean If ``false``, this variation will not be sold or shown.
|
||||
@@ -154,8 +130,6 @@ variations list of objects A list with o
|
||||
├ checkin_attention boolean If ``true``, the check-in app should show a warning
|
||||
that this ticket requires special attention if such
|
||||
a variation is being scanned.
|
||||
├ checkin_text string Text that will be shown if a ticket of this type is
|
||||
scanned (or ``null``).
|
||||
├ require_approval boolean If ``true``, orders with this variation will need to be
|
||||
approved by the event organizer before they can be
|
||||
paid.
|
||||
@@ -164,26 +138,15 @@ variations list of objects A list with o
|
||||
be hidden from users without a valid membership.
|
||||
├ require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
|
||||
Markdown syntax or can be ``null``.
|
||||
├ all_sales_channels boolean If ``true`` (default), the variation is available on all sales channels.
|
||||
├ limit_sales_channels list of strings List of sales channel identifiers the variation is available on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
├ sales_channels list of strings Sales channels this variation is available on, such as
|
||||
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
|
||||
The item-level list takes precedence, i.e. a sales
|
||||
channel needs to be on both lists for the variation to be
|
||||
available (unless ``all_sales_channels`` is used).
|
||||
├ sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
|
||||
and ``limit_sales_channels`` instead.
|
||||
channel needs to be on both lists for the item to be
|
||||
available.
|
||||
├ available_from datetime The first date time at which this variation can be bought
|
||||
(or ``null``).
|
||||
├ available_from_mode string If ``hide`` (the default), this variation is hidden in the shop
|
||||
if unavailable due to the ``available_from`` setting.
|
||||
If ``info``, the variation is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
├ available_until datetime The last date time at which this variation can be bought
|
||||
(or ``null``).
|
||||
├ available_until_mode string If ``hide`` (the default), this variation is hidden in the shop
|
||||
if unavailable due to the ``available_until`` setting.
|
||||
If ``info``, the variation is visible, but can't be purchased,
|
||||
and a note explaining the unavailability is displayed.
|
||||
├ hide_without_voucher boolean If ``true``, this variation is only shown during the voucher
|
||||
redemption process, but not in the normal shop
|
||||
frontend.
|
||||
@@ -233,20 +196,6 @@ meta_data object Values set fo
|
||||
|
||||
The ``media_policy`` and ``media_type`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 2023.10
|
||||
|
||||
The ``checkin_text`` and ``variations[x].checkin_text`` attributes have been added.
|
||||
The ``free_price_suggestion`` and ``variations[x].free_price_suggestion`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 2023.10
|
||||
|
||||
The ``hidden_if_item_available`` attributes has been added, the ``hidden_if_available`` attribute has been
|
||||
deprecated.
|
||||
|
||||
.. versionchanged:: 2025.01
|
||||
|
||||
The ``hidden_if_item_available_mode`` attributes has been added.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
@@ -290,8 +239,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
@@ -299,7 +246,6 @@ Endpoints
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"free_price_suggestion": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
@@ -311,19 +257,14 @@ Endpoints
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hidden_if_available": null,
|
||||
"hidden_if_item_available": null,
|
||||
"hidden_if_item_available_mode": "hide",
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"has_variations": false,
|
||||
"generate_tickets": null,
|
||||
"allow_waitinglist": true,
|
||||
@@ -350,20 +291,14 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -374,20 +309,14 @@ Endpoints
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -401,7 +330,6 @@ Endpoints
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string search: Filter the list by internal name or name of the item (substring search).
|
||||
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
|
||||
returned.
|
||||
:query integer category: If set to the ID of a category, only items within that category will be returned.
|
||||
@@ -442,8 +370,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
@@ -451,7 +377,6 @@ Endpoints
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"free_price_suggestion": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
@@ -463,12 +388,8 @@ Endpoints
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hidden_if_available": null,
|
||||
"hidden_if_item_available": null,
|
||||
"hidden_if_item_available_mode": "hide",
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
@@ -478,7 +399,6 @@ Endpoints
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"has_variations": false,
|
||||
"require_approval": false,
|
||||
"require_bundling": false,
|
||||
@@ -502,21 +422,15 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"description": null,
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"meta_data": {},
|
||||
"position": 0
|
||||
@@ -526,20 +440,14 @@ Endpoints
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -574,15 +482,13 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"free_price_suggestion": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
@@ -594,12 +500,8 @@ Endpoints
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hidden_if_available": null,
|
||||
"hidden_if_item_available": null,
|
||||
"hidden_if_item_available_mode": "hide",
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
@@ -609,7 +511,6 @@ Endpoints
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_bundling": false,
|
||||
"require_membership": false,
|
||||
@@ -632,19 +533,14 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -655,19 +551,14 @@ Endpoints
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -690,8 +581,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
@@ -699,7 +588,6 @@ Endpoints
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"free_price_suggestion": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
@@ -711,12 +599,8 @@ Endpoints
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hidden_if_available": null,
|
||||
"hidden_if_item_available": null,
|
||||
"hidden_if_item_available_mode": "hide",
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
@@ -726,7 +610,6 @@ Endpoints
|
||||
"allow_waitinglist": true,
|
||||
"show_quota_left": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"has_variations": true,
|
||||
"require_approval": false,
|
||||
"require_bundling": false,
|
||||
@@ -750,20 +633,14 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -774,20 +651,14 @@ Endpoints
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -841,8 +712,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "Ticket"},
|
||||
"internal_name": "",
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"default_price": "25.00",
|
||||
"original_price": null,
|
||||
@@ -850,7 +719,6 @@ Endpoints
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"free_price_suggestion": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
@@ -862,12 +730,8 @@ Endpoints
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hidden_if_available": null,
|
||||
"hidden_if_item_available": null,
|
||||
"hidden_if_item_available_mode": "hide",
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"generate_tickets": null,
|
||||
@@ -877,7 +741,6 @@ Endpoints
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"has_variations": true,
|
||||
"require_approval": false,
|
||||
"require_bundling": false,
|
||||
@@ -901,20 +764,14 @@ Endpoints
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
@@ -925,20 +782,14 @@ Endpoints
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"original_price": null,
|
||||
"free_price_suggestion": null,
|
||||
"active": true,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"require_membership": false,
|
||||
"require_membership_types": [],
|
||||
"all_sales_channels": false,
|
||||
"limit_sales_channels": ["web"],
|
||||
"sales_channels": ["web"],
|
||||
"available_from": null,
|
||||
"available_from_mode": "hide",
|
||||
"available_until": null,
|
||||
"available_until_mode": "hide",
|
||||
"hide_without_voucher": false,
|
||||
"description": null,
|
||||
"meta_data": {},
|
||||
|
||||
@@ -20,7 +20,6 @@ The order resource contains the following public fields:
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
code string Order code
|
||||
event string The slug of the parent event
|
||||
status string Order status, one of:
|
||||
|
||||
* ``n`` – pending
|
||||
@@ -42,14 +41,10 @@ payment_date date **DEPRECATED AN
|
||||
payment_provider string **DEPRECATED AND INACCURATE** Payment provider used for this order
|
||||
total money (string) Total value of this order
|
||||
comment string Internal comment on this order
|
||||
api_meta object Meta data for that order. Only available through API, no guarantees
|
||||
on the content structure. You can use this to save references to your system.
|
||||
custom_followup_at date Internal date for a custom follow-up action
|
||||
checkin_attention boolean If ``true``, the check-in app should show a warning
|
||||
that this ticket requires special attention if a ticket
|
||||
of this order is scanned.
|
||||
checkin_text string Text that will be shown if a ticket of this order is
|
||||
scanned (or ``null``).
|
||||
invoice_address object Invoice address information (can be ``null``)
|
||||
├ last_modified datetime Last modification date of the address
|
||||
├ company string Customer company name
|
||||
@@ -84,7 +79,6 @@ fees list of objects List of fees in
|
||||
├ tax_rate decimal (string) VAT rate applied for this fee
|
||||
├ tax_value money (string) VAT included in this fee
|
||||
├ tax_rule integer The ID of the used tax rule (or ``null``)
|
||||
├ tax_code string Codified reason for tax rate (or ``null``), see :ref:`rest-taxcodes`.
|
||||
└ canceled boolean Whether or not this fee has been canceled.
|
||||
downloads list of objects List of ticket download options for order-wise ticket
|
||||
downloading. This might be a multi-page PDF or a ZIP
|
||||
@@ -105,11 +99,6 @@ url string The full URL to
|
||||
payments list of objects List of payment processes (see below)
|
||||
refunds list of objects List of refund processes (see below)
|
||||
last_modified datetime Last modification of this object
|
||||
cancellation_date datetime Time of order cancellation (or ``null``). **Note**:
|
||||
Will not be set for partial cancellations and is not
|
||||
reliable for orders that have been cancelled,
|
||||
reactivated and cancelled again.
|
||||
plugin_data object Additional data added by plugins.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -141,33 +130,6 @@ plugin_data object Additional data
|
||||
|
||||
The ``valid_if_pending`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2023.8
|
||||
|
||||
The ``event`` attribute has been added. The organizer-level endpoint has been added.
|
||||
|
||||
.. versionchanged:: 2023.9
|
||||
|
||||
The ``customer`` query parameter has been added.
|
||||
|
||||
.. versionchanged:: 2023.10
|
||||
|
||||
The ``checkin_text`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2024.1
|
||||
|
||||
The ``expires`` attribute can now be passed during order creation.
|
||||
|
||||
.. versionchanged:: 2024.11
|
||||
|
||||
The ``cancellation_date`` attribute has been added and can also be used as an ordering key.
|
||||
|
||||
.. versionchanged:: 2025.1
|
||||
|
||||
The ``tax_code`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2025.2
|
||||
|
||||
The ``plugin_data`` attribute has been added.
|
||||
|
||||
.. _order-position-resource:
|
||||
|
||||
@@ -198,14 +160,8 @@ country string Attendee countr
|
||||
state string Attendee state (ISO 3166-2 code). Only supported in
|
||||
AU, BR, CA, CN, MY, MX, and US, otherwise ``null``.
|
||||
voucher integer Internal ID of the voucher used for this position (or ``null``)
|
||||
voucher_budget_use money (string) Amount of money discounted by the voucher, corresponding
|
||||
to how much of the ``budget`` of the voucher is consumed.
|
||||
**Important:** Do not rely on this amount to be a useful
|
||||
value if the position's price, product or voucher
|
||||
are changed *after* the order was created. Can be ``null``.
|
||||
tax_rate decimal (string) VAT rate applied for this position
|
||||
tax_value money (string) VAT included in this position
|
||||
tax_code string Codified reason for tax rate (or ``null``), see :ref:`rest-taxcodes`.
|
||||
tax_rule integer The ID of the used tax rule (or ``null``)
|
||||
secret string Secret code printed on the tickets for validation
|
||||
addon_to integer Internal ID of the position this position is an add-on for (or ``null``)
|
||||
@@ -221,20 +177,8 @@ checkins list of objects List of **succe
|
||||
├ datetime datetime Time of check-in
|
||||
├ type string Type of scan (defaults to ``entry``)
|
||||
├ gate integer Internal ID of the gate. Can be ``null``.
|
||||
├ device integer Internal ID of the device. Can be ``null``. **Deprecated**, since this ID is not otherwise used in the API and is therefore not very useful.
|
||||
├ device_id integer Attribute ``device_id`` of the device. Can be ``null``.
|
||||
├ device integer Internal ID of the device. Can be ``null``.
|
||||
└ auto_checked_in boolean Indicates if this check-in been performed automatically by the system
|
||||
print_logs list of objects List of print jobs recorded e.g. by the pretix apps
|
||||
├ id integer Internal ID of the print job
|
||||
├ successful boolean Whether the print job successfully resulted in a print.
|
||||
This is not expected to be 100 % reliable information (since
|
||||
printer feedback is never perfect) and there is no guarantee
|
||||
that unsuccessful jobs will be logged.
|
||||
├ device_id integer Attribute ``device_id`` of the device that recorded the print. Can be ``null``.
|
||||
├ datetime datetime Time of printing
|
||||
├ source string Source of print job, e.g. name of the app used.
|
||||
├ type string Type of print (currently ``badge``, ``ticket``, ``certificate``, or ``other``)
|
||||
└ info object Additional data with client-dependent structure.
|
||||
downloads list of objects List of ticket download options
|
||||
├ output string Ticket output provider (e.g. ``pdf``, ``passbook``)
|
||||
└ url string Download URL
|
||||
@@ -247,34 +191,16 @@ answers list of objects Answers to user
|
||||
seat objects The assigned seat. Can be ``null``.
|
||||
├ id integer Internal ID of the seat instance
|
||||
├ name string Human-readable seat name
|
||||
├ zone_name string Name of the zone the seat is in
|
||||
├ row_name string Name/number of the row the seat is in
|
||||
├ row_label string Additional label of the row (or ``null``)
|
||||
├ seat_number string Number of the seat within the row
|
||||
├ seat_label string Additional label of the seat (or ``null``)
|
||||
└ seat_guid string Identifier of the seat within the seating plan
|
||||
pdf_data object Data object required for ticket PDF generation. By default,
|
||||
this field is missing. It will be added only if you add the
|
||||
``pdf_data=true`` query parameter to your request.
|
||||
plugin_data object Additional data added by plugins.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 4.16
|
||||
|
||||
The attributes ``blocked``, ``valid_from`` and ``valid_until`` have been added.
|
||||
|
||||
.. versionchanged:: 2024.9
|
||||
|
||||
The attribute ``print_logs`` has been added.
|
||||
|
||||
.. versionchanged:: 2025.1
|
||||
|
||||
The ``tax_code`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2025.2
|
||||
|
||||
The ``plugin_data`` attribute has been added.
|
||||
|
||||
.. _order-payment-resource:
|
||||
|
||||
Order payment resource
|
||||
@@ -363,7 +289,6 @@ List of all orders
|
||||
"results": [
|
||||
{
|
||||
"code": "ABC12",
|
||||
"event": "sampleconf",
|
||||
"status": "p",
|
||||
"testmode": false,
|
||||
"secret": "k24fiuwvu8kxz3y1",
|
||||
@@ -383,7 +308,6 @@ List of all orders
|
||||
"comment": "",
|
||||
"custom_followup_at": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"valid_if_pending": false,
|
||||
"invoice_address": {
|
||||
@@ -422,11 +346,9 @@ List of all orders
|
||||
"country": "DE",
|
||||
"state": null,
|
||||
"voucher": null,
|
||||
"voucher_budget_use": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_code": null,
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
@@ -442,21 +364,10 @@ List of all orders
|
||||
"type": "entry",
|
||||
"gate": null,
|
||||
"device": 2,
|
||||
"device_id": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"auto_checked_in": false
|
||||
}
|
||||
],
|
||||
"print_logs": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "badge",
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"device_id": 1,
|
||||
"source": "pretixSCAN",
|
||||
"info": {}
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
@@ -471,8 +382,7 @@ List of all orders
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
],
|
||||
"plugin_data": {}
|
||||
]
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
@@ -493,20 +403,17 @@ List of all orders
|
||||
"provider": "banktransfer"
|
||||
}
|
||||
],
|
||||
"refunds": [],
|
||||
"cancellation_date": null,
|
||||
"plugin_data": {}
|
||||
"refunds": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``code``,
|
||||
``last_modified``, ``status`` and ``cancellation_date``. Default: ``datetime``
|
||||
``last_modified``, and ``status``. Default: ``datetime``
|
||||
:query string code: Only return orders that match the given order code
|
||||
:query string status: Only return orders in the given order status (see above)
|
||||
:query string search: Only return orders matching a given search query (matching for names, email addresses, and company names)
|
||||
:query string customer: Only show orders linked to the given customer.
|
||||
:query integer item: Only return orders with a position that contains this item ID. *Warning:* Result will also include orders if they contain mixed items, and it will even return orders where the item is only contained in a canceled position.
|
||||
:query integer variation: Only return orders with a position that contains this variation ID. *Warning:* Result will also include orders if they contain mixed items and variations, and it will even return orders where the variation is only contained in a canceled position.
|
||||
:query boolean testmode: Only return orders with ``testmode`` set to ``true`` or ``false``
|
||||
@@ -520,13 +427,10 @@ List of all orders
|
||||
:query datetime modified_since: Only return orders that have changed since the given date. Be careful: We only
|
||||
recommend using this in combination with ``testmode=false``, since test mode orders can vanish at any time and
|
||||
you will not notice it using this method.
|
||||
:query datetime created_since: Only return orders that have been created since the given date (inclusive).
|
||||
:query datetime created_before: Only return orders that have been created before the given date (exclusive).
|
||||
:query datetime created_since: Only return orders that have been created since the given date.
|
||||
:query integer subevent: Only return orders with a position that contains this subevent ID. *Warning:* Result will also include orders if they contain mixed subevents, and it will even return orders where the subevent is only contained in a canceled position.
|
||||
:query datetime subevent_after: Only return orders that contain a ticket for a subevent taking place after the given date. This is an exclusive after, and it considers the **end** of the subevent (or its start, if the end is not set).
|
||||
:query datetime subevent_before: Only return orders that contain a ticket for a subevent taking place after the given date. This is an exclusive before, and it considers the **start** of the subevent.
|
||||
:query string sales_channel: Only return orders with the given sales channel identifier (e.g. ``"web"``).
|
||||
:query string payment_provider: Only return orders that contain a payment using the given payment provider. Note that this also searches for partial incomplete, or failed payments within the order and is not useful to get a sum of payment amounts without further processing.
|
||||
:query string exclude: Exclude a field from the output, e.g. ``fees`` or ``positions.downloads``. Can be used as a performance optimization. Can be passed multiple times.
|
||||
:query string include: Include only the given field in the output, e.g. ``fees`` or ``positions.downloads``. Can be used as a performance optimization. Can be passed multiple times. ``include`` is applied before ``exclude``, so ``exclude`` takes precedence.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -537,48 +441,6 @@ List of all orders
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/orders/
|
||||
|
||||
Returns a list of all orders within all events of a given organizer (with sufficient access permissions).
|
||||
|
||||
Supported query parameters and output format of this endpoint are identical to the list endpoint within an event,
|
||||
with the exception that the ``pdf_data`` parameter is not supported here.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/orders/ 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
|
||||
X-Page-Generated: 2017-12-01T10:00:00Z
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"code": "ABC12",
|
||||
"event": "sampleconf",
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
Fetching individual orders
|
||||
--------------------------
|
||||
|
||||
@@ -604,7 +466,6 @@ Fetching individual orders
|
||||
|
||||
{
|
||||
"code": "ABC12",
|
||||
"event": "sampleconf",
|
||||
"status": "p",
|
||||
"testmode": false,
|
||||
"secret": "k24fiuwvu8kxz3y1",
|
||||
@@ -622,10 +483,8 @@ Fetching individual orders
|
||||
"fees": [],
|
||||
"total": "23.00",
|
||||
"comment": "",
|
||||
"api_meta": {},
|
||||
"custom_followup_at": null,
|
||||
"checkin_attention": false,
|
||||
"checkin_text": null,
|
||||
"require_approval": false,
|
||||
"valid_if_pending": false,
|
||||
"invoice_address": {
|
||||
@@ -664,11 +523,9 @@ Fetching individual orders
|
||||
"country": "DE",
|
||||
"state": null,
|
||||
"voucher": null,
|
||||
"voucher_budget_use": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_value": "0.00",
|
||||
"tax_code": null,
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
@@ -684,22 +541,10 @@ Fetching individual orders
|
||||
"type": "entry",
|
||||
"gate": null,
|
||||
"device": 2,
|
||||
"device_id": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"auto_checked_in": false
|
||||
}
|
||||
],
|
||||
"print_logs": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "badge",
|
||||
"successful": true,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"device_id": 1,
|
||||
"source": "pretixSCAN",
|
||||
"info": {}
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
@@ -714,8 +559,7 @@ Fetching individual orders
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
],
|
||||
"plugin_data": {}
|
||||
]
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
@@ -736,9 +580,7 @@ Fetching individual orders
|
||||
"provider": "banktransfer"
|
||||
}
|
||||
],
|
||||
"refunds": [],
|
||||
"cancellation_date": null,
|
||||
"plugin_data": {}
|
||||
"refunds": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -813,22 +655,16 @@ Updating order fields
|
||||
|
||||
* ``checkin_attention``
|
||||
|
||||
* ``checkin_text``
|
||||
|
||||
* ``locale``
|
||||
|
||||
* ``comment``
|
||||
|
||||
* ``api_meta``
|
||||
|
||||
* ``custom_followup_at``
|
||||
|
||||
* ``invoice_address`` (you always need to supply the full object, or ``null`` to delete the current address)
|
||||
|
||||
* ``valid_if_pending``
|
||||
|
||||
* ``expires``
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
@@ -869,7 +705,7 @@ Generating new secrets
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/regenerate_secrets/
|
||||
|
||||
Triggers generation of new ``secret`` and ``web_secret`` attributes for both the order and all order positions.
|
||||
Triggers generation of new ``secret`` attributes for both the order and all order positions.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -900,7 +736,7 @@ Generating new secrets
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/regenerate_secrets/
|
||||
|
||||
Triggers generation of a new ``secret`` and ``web_secret`` attribute for a single order position.
|
||||
Triggers generation of a new ``secret`` attribute for a single order position.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -1034,7 +870,6 @@ Creating orders
|
||||
* ``comment`` (optional)
|
||||
* ``custom_followup_at`` (optional)
|
||||
* ``checkin_attention`` (optional)
|
||||
* ``checkin_text`` (optional)
|
||||
* ``require_approval`` (optional)
|
||||
* ``valid_if_pending`` (optional)
|
||||
* ``invoice_address`` (optional)
|
||||
@@ -1050,8 +885,8 @@ Creating orders
|
||||
* ``internal_reference``
|
||||
* ``vat_id``
|
||||
* ``vat_id_validated`` (optional) – If you need support for reverse charge (rarely the case), you need to check
|
||||
yourself if the passed VAT ID is a valid EU VAT ID. In that case, set this to ``true``. Only valid VAT IDs will
|
||||
trigger reverse charge taxation. Don't forget to set ``is_business`` as well!
|
||||
yourself if the passed VAT ID is a valid EU VAT ID. In that case, set this to ``true``. Only valid VAT IDs will
|
||||
trigger reverse charge taxation. Don't forget to set ``is_business`` as well!
|
||||
|
||||
* ``positions``
|
||||
|
||||
@@ -1635,11 +1470,9 @@ List of all order positions
|
||||
},
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"voucher_budget_use": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_value": "0.00",
|
||||
"tax_code": null,
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"discount": null,
|
||||
"pseudonymization_id": "MQLJvANO3B",
|
||||
@@ -1655,22 +1488,10 @@ List of all order positions
|
||||
"type": "entry",
|
||||
"gate": null,
|
||||
"device": 2,
|
||||
"device_id": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"auto_checked_in": false
|
||||
}
|
||||
],
|
||||
"print_logs": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "badge",
|
||||
"successful": true,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"device_id": 1,
|
||||
"source": "pretixSCAN",
|
||||
"info": {}
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
@@ -1685,8 +1506,7 @@ List of all order positions
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
],
|
||||
"plugin_data": {}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1697,7 +1517,6 @@ List of all order positions
|
||||
``order__datetime,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query string search: Fuzzy search matching the attendee name, order code, invoice address name as well as to the beginning of the secret.
|
||||
:query string customer: Only show orders linked to the given customer.
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
@@ -1763,11 +1582,9 @@ Fetching individual positions
|
||||
},
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"voucher_budget_use": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_value": "0.00",
|
||||
"tax_code": null,
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
@@ -1783,22 +1600,10 @@ Fetching individual positions
|
||||
"type": "entry",
|
||||
"gate": null,
|
||||
"device": 2,
|
||||
"device_id": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"auto_checked_in": false
|
||||
}
|
||||
],
|
||||
"print_logs": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "badge",
|
||||
"successful": true,
|
||||
"datetime": "2017-12-25T12:45:23Z",
|
||||
"device_id": 1,
|
||||
"source": "pretixSCAN",
|
||||
"info": {}
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
@@ -1813,8 +1618,7 @@ Fetching individual positions
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
],
|
||||
"plugin_data": {}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -1896,10 +1700,6 @@ Manipulating individual positions
|
||||
|
||||
The endpoints to manage blocks have been added.
|
||||
|
||||
.. versionchanged:: 2024.9
|
||||
|
||||
The API now supports logging ticket and badge prints.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/
|
||||
|
||||
Updates specific fields on an order position. Currently, only the following fields are supported:
|
||||
@@ -2159,59 +1959,6 @@ Manipulating individual positions
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to update this order position.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/printlog/
|
||||
|
||||
Creates a print log, stating that this ticket has been printed.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/printlog/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"datetime": "2024-09-19T13:37:00+02:00",
|
||||
"source": "pretixPOS",
|
||||
"type": "badge",
|
||||
"info": {
|
||||
"cashier": 1234
|
||||
}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
{
|
||||
"id": 1234,
|
||||
"device_id": null,
|
||||
"datetime": "2024-09-19T13:37:00+02:00",
|
||||
"source": "pretixPOS",
|
||||
"type": "badge",
|
||||
"info": {
|
||||
"cashier": 1234
|
||||
}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a log for
|
||||
:param event: The ``slug`` field of the event to create a log for
|
||||
:param id: The ``id`` field of the order position to create a log for
|
||||
:statuscode 201: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource
|
||||
**or** downloads are not available for this order position at this time. The response content will
|
||||
contain more details.
|
||||
:statuscode 404: The requested order position or download provider does not exist.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting for a few
|
||||
seconds.
|
||||
|
||||
Changing order contents
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@ identifier string An arbitrary st
|
||||
ask_during_checkin boolean If ``true``, this question will not be asked while
|
||||
buying the ticket, but will show up when redeeming
|
||||
the ticket instead.
|
||||
show_during_checkin boolean If ``true``, the answer to the question will be shown
|
||||
during check-in (if the check-in client supports it).
|
||||
hidden boolean If ``true``, the question will only be shown in the
|
||||
backend.
|
||||
print_on_invoice boolean If ``true``, the question will only be shown on
|
||||
@@ -79,10 +77,6 @@ dependency_value string An old version
|
||||
for one value. **Deprecated.**
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 2023.8
|
||||
|
||||
The ``show_during_checkin`` attribute has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -121,7 +115,6 @@ Endpoints
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"show_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"valid_number_min": null,
|
||||
@@ -201,7 +194,6 @@ Endpoints
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"show_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"valid_number_min": null,
|
||||
@@ -265,7 +257,6 @@ Endpoints
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"ask_during_checkin": false,
|
||||
"show_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"dependency_question": null,
|
||||
@@ -302,7 +293,6 @@ Endpoints
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"show_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"dependency_question": null,
|
||||
@@ -358,7 +348,7 @@ Endpoints
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
@@ -386,7 +376,6 @@ Endpoints
|
||||
"position": 2,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"show_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"dependency_question": null,
|
||||
@@ -426,7 +415,7 @@ Endpoints
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The question could not be modified due to invalid submitted data
|
||||
:statuscode 400: The item could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
@@ -438,7 +427,7 @@ Endpoints
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
@@ -451,7 +440,7 @@ Endpoints
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to delete
|
||||
:param id: The ``id`` field of the item to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
Sales channels
|
||||
==============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The sales channel resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
identifier string Internal ID of the sales channel. For sales channel types
|
||||
that allow only one instance, this is the same as ``type``.
|
||||
For sales channel types that allow multiple instances, this
|
||||
is always prefixed with ``type.``.
|
||||
label multi-lingual string Human-readable name of the sales channel
|
||||
type string Type of the sales channel. Only channels with type ``api``
|
||||
can currently be created through the API.
|
||||
position integer Position for sorting lists of sales channels
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/saleschannels/
|
||||
|
||||
Returns a list of all sales channels within a given organizer.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/saleschannels/ 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": [
|
||||
{
|
||||
"identifier": "web",
|
||||
"label": {
|
||||
"en": "Online shop"
|
||||
},
|
||||
"type": "web",
|
||||
"position": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
|
||||
|
||||
Returns information on one sales channel, identified by its identifier.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/saleschannels/web/ 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
|
||||
|
||||
{
|
||||
"identifier": "web",
|
||||
"label": {
|
||||
"en": "Online shop"
|
||||
},
|
||||
"type": "web",
|
||||
"position": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param identifier: The ``identifier`` field of the sales channel to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/saleschannels/
|
||||
|
||||
Creates a sales channel
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/saleschannels/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "api.custom",
|
||||
"label": {
|
||||
"en": "Custom integration"
|
||||
},
|
||||
"type": "api",
|
||||
"position": 2
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "api.custom",
|
||||
"label": {
|
||||
"en": "Custom integration"
|
||||
},
|
||||
"type": "api",
|
||||
"position": 2
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a sales channel for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The sales channel could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
|
||||
|
||||
Update a sales channel. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``identifier`` and ``type`` fields.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/saleschannels/web/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"position": 5
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "web",
|
||||
"label": {
|
||||
"en": "Online shop"
|
||||
},
|
||||
"type": "web",
|
||||
"position": 5
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param identifier: The ``identifier`` field of the sales channel to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The sales channel could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
|
||||
|
||||
Delete a sales channel. You can not delete sales channels which have already been used or which are integral parts
|
||||
of the system.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/saleschannels/api.custom/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param identifier: The ``identifier`` field of the sales channel to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource **or** the sales channel is currently in use.
|
||||
@@ -1,556 +0,0 @@
|
||||
.. spelling:word-list:: checkin
|
||||
|
||||
Scheduled data exports
|
||||
======================
|
||||
|
||||
pretix and it's plugins include a number of data exporters that allow you to bulk download various data from pretix in
|
||||
different formats. You should read :ref:`rest-exporters` first to get an understanding of the basic mechanism.
|
||||
|
||||
Exports can be scheduled to be sent at specific times automatically, both on organizer level and event level.
|
||||
|
||||
Scheduled export resource
|
||||
-------------------------
|
||||
|
||||
The scheduled export contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the schedule
|
||||
owner string Email address of the user who created this schedule (read-only).
|
||||
This address will always receive the export and the export
|
||||
will only contain data that this user has permission
|
||||
to access at the time of the export. **We consider this
|
||||
field experimental, it's behaviour might change in the future.
|
||||
Note that the email address of a user can change at any time.**
|
||||
export_identifier string Identifier of the export to run, see :ref:`rest-exporters`
|
||||
export_form_data object Input data for the export, format depends on the export,
|
||||
see :ref:`rest-exporters` for more details.
|
||||
locale string Language to run the export in
|
||||
mail_additional_recipients string Email addresses to receive the export, comma-separated (or empty string)
|
||||
mail_additional_recipients_cc string Email addresses to receive the export in copy, comma-separated (or empty string)
|
||||
mail_additional_recipients_bcc string Email addresses to receive the exportin blind copy, comma-separated (or empty string)
|
||||
mail_subject string Subject to use for the email (currently no variables supported)
|
||||
mail_template string Text to use for the email (currently no variables supported)
|
||||
schedule_rrule string Recurrence specification to determine the **days** this
|
||||
schedule runs on in ``RRULE`` syntax following `RFC 5545`_
|
||||
with some restrictions. Only one rule is allowed, only
|
||||
one occurrence per day is allowed, and some features
|
||||
are not supported (``BYMONTHDAY``, ``BYYEARDAY``,
|
||||
``BYEASTER``, ``BYWEEKNO``).
|
||||
schedule_rrule_time time Time of day to run this on on the specified days.
|
||||
Will be interpreted as local time of the event for event-level
|
||||
exports. For organizer-level exports, the timezone is given
|
||||
in the field ``timezone``. The export will never run **before**
|
||||
this time but it **may** run **later**.
|
||||
timezone string Time zone to interpret the schedule in (only for organizer-level exports)
|
||||
schedule_next_run datetime Next planned execution (read-only, computed by server)
|
||||
error_counter integer Number of consecutive times this export failed (read-only).
|
||||
After a number of failures (currently 5), the schedule no
|
||||
longer is executed. Changing parameters resets the value.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Special notes on permissions
|
||||
----------------------------
|
||||
|
||||
Permission handling for scheduled exports is more complex than for most other objects. The reason for this is that
|
||||
there are two levels of access control involved here: First, you need permission to access or change the configuration
|
||||
of the scheduled exports in the moment you are doing it. Second, you **continuously** need permission to access the
|
||||
**data** that is exported as part of the schedule. For this reason, scheduled exports always need one user account
|
||||
to be their **owner**.
|
||||
|
||||
Therefore, scheduled exports **must** be created by an API client using :ref:`OAuth authentication <rest-oauth>`.
|
||||
It is impossible to create a scheduled export using token authentication. After the export is created, it can also be
|
||||
modified using token authentication.
|
||||
|
||||
A user or token with the "can change settings" permission for a given organizer or event can see and change
|
||||
**all** scheduled exports created for the respective organizer or event, regardless of who created them.
|
||||
A user without this permission can only see **their own** scheduled exports.
|
||||
A token without this permission can not see scheduled exports as all.
|
||||
|
||||
|
||||
|
||||
Endpoints for event exports
|
||||
---------------------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/
|
||||
|
||||
Returns a list of all scheduled exports the client has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/ 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,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"error_counter": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``export_identifier``, and ``schedule_next_run``.
|
||||
Default: ``id``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
|
||||
|
||||
Returns information on one scheduled export, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/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,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the scheduled export to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/
|
||||
|
||||
Schedule a new export.
|
||||
|
||||
.. note:: See above for special notes on permissions.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||
:param event: The ``slug`` field of the event to create an item for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
|
||||
|
||||
Update a scheduled export. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the export to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The export could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
|
||||
|
||||
Delete a scheduled export.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the export to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
Endpoints for organizer exports
|
||||
-------------------------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/scheduled_exports/
|
||||
|
||||
Returns a list of all scheduled exports the client has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/scheduled_exports/ 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,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"timezone": "Europe/Berlin",
|
||||
"error_counter": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``export_identifier``, and ``schedule_next_run``.
|
||||
Default: ``id``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
|
||||
|
||||
Returns information on one scheduled export, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/scheduled_exports/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,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"timezone": "Europe/Berlin",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param id: The ``id`` field of the scheduled export to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/scheduled_exports/
|
||||
|
||||
Schedule a new export.
|
||||
|
||||
.. note:: See above for special notes on permissions.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/scheduled_exports/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"timezone": "Europe/Berlin"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"timezone": "Europe/Berlin",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
|
||||
|
||||
Update a scheduled export. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/scheduled_exports/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"owner": "john@example.com",
|
||||
"export_identifier": "orderlist",
|
||||
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
|
||||
"locale": "en",
|
||||
"mail_additional_recipients": "mary@example.org",
|
||||
"mail_additional_recipients_cc": "",
|
||||
"mail_additional_recipients_bcc": "",
|
||||
"mail_subject": "Order list",
|
||||
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
|
||||
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
|
||||
"schedule_rrule_time": "04:00:00",
|
||||
"schedule_next_run": "2023-10-26T02:00:00Z",
|
||||
"timezone": "Europe/Berlin",
|
||||
"error_counter": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param id: The ``id`` field of the export to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The export could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
|
||||
|
||||
Delete a scheduled export.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/scheduled_exports/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param id: The ``id`` field of the export to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
|
||||
.. _RFC 5545: https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.5.3
|
||||
@@ -1,373 +0,0 @@
|
||||
.. _`rest-seats`:
|
||||
|
||||
Seats
|
||||
=====
|
||||
|
||||
The seat resource represents the seats in a seating plan in a specific event or subevent.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The seat resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of this seat
|
||||
subevent integer Internal ID of the subevent this seat belongs to
|
||||
zone_name string Name of the zone the seat is in
|
||||
row_name string Name/number of the row the seat is in
|
||||
row_label string Additional label of the row (or ``null``)
|
||||
seat_number string Number of the seat within the row
|
||||
seat_label string Additional label of the seat (or ``null``)
|
||||
seat_guid string Identifier of the seat within the seating plan
|
||||
product integer Internal ID of the product that is mapped to this seat
|
||||
blocked boolean Whether this seat is blocked manually.
|
||||
orderposition integer / object Internal ID of an order position reserving this seat.
|
||||
cartposition integer / object Internal ID of a cart position reserving this seat.
|
||||
voucher integer / object Internal ID of a voucher reserving this seat.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/seats/
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(subevent_id)/seats/
|
||||
|
||||
Returns a list of all seats in the specified event or subevent. Depending on whether the event has subevents, the
|
||||
according endpoint has to be used.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/seats/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 500,
|
||||
"next": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/seats/?page=2",
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1633,
|
||||
"subevent": null,
|
||||
"zone_name": "Ground floor",
|
||||
"row_name": "1",
|
||||
"row_label": null,
|
||||
"seat_number": "1",
|
||||
"seat_label": null,
|
||||
"seat_guid": "b9746230-6f31-4f41-bbc9-d6b60bdb3342",
|
||||
"product": 104,
|
||||
"blocked": false,
|
||||
"orderposition": null,
|
||||
"cartposition": null,
|
||||
"voucher": 51
|
||||
},
|
||||
{
|
||||
"id": 1634,
|
||||
"subevent": null,
|
||||
"zone_name": "Ground floor",
|
||||
"row_name": "1",
|
||||
"row_label": null,
|
||||
"seat_number": "2",
|
||||
"seat_label": null,
|
||||
"seat_guid": "1d29fe20-8e1e-4984-b0ee-2773b0d07e07",
|
||||
"product": 104,
|
||||
"blocked": true,
|
||||
"orderposition": 4321,
|
||||
"cartposition": null,
|
||||
"voucher": null
|
||||
},
|
||||
// ...
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1.
|
||||
:query string zone_name: Only show seats with the given zone_name.
|
||||
:query string row_name: Only show seats with the given row_name.
|
||||
:query string row_label: Only show seats with the given row_label.
|
||||
:query string seat_number: Only show seats with the given seat_number.
|
||||
:query string seat_label: Only show seats with the given seat_label.
|
||||
:query string seat_guid: Only show seats with the given seat_guid.
|
||||
:query boolean blocked: Only show seats with the given blocked status.
|
||||
:query boolean is_available: Only show seats that are (not) currently available.
|
||||
:query string expand: If you pass ``"orderposition"``, ``"cartposition"``, or ``"voucher"``, the respective field will be
|
||||
shown as a nested value instead of just an ID. This requires permission to access that object.
|
||||
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
|
||||
matching easier, and won't include the `seat` attribute, as that would be redundant.
|
||||
The parameter can be given multiple times.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param subevent_id: The ``id`` field of the subevent to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: Endpoint without subevent id was used for event with subevents, or vice versa.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/seats/(id)/
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(subevent_id)/seats/(id)/
|
||||
|
||||
Returns information on one seat, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/seats/1634/?expand=orderposition HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1634,
|
||||
"subevent": null,
|
||||
"zone_name": "Ground floor",
|
||||
"row_name": "1",
|
||||
"row_label": null,
|
||||
"seat_number": "2",
|
||||
"seat_label": null,
|
||||
"seat_guid": "1d29fe20-8e1e-4984-b0ee-2773b0d07e07",
|
||||
"product": 104,
|
||||
"blocked": true,
|
||||
"orderposition": {
|
||||
"id": 134,
|
||||
"order": {
|
||||
"code": "U0HW7",
|
||||
"event": "sampleconf"
|
||||
},
|
||||
"positionid": 1,
|
||||
"item": 104,
|
||||
"variation": 59,
|
||||
"price": "60.00",
|
||||
"attendee_name": "",
|
||||
"attendee_name_parts": {
|
||||
"_scheme": "given_family"
|
||||
},
|
||||
"company": null,
|
||||
"street": null,
|
||||
"zipcode": null,
|
||||
"city": null,
|
||||
"country": null,
|
||||
"state": null,
|
||||
"discount": null,
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"secret": "4rfgp263jduratnsvwvy6cc6r6wnptbj",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"checkins": [],
|
||||
"downloads": [],
|
||||
"answers": [],
|
||||
"tax_rule": null,
|
||||
"pseudonymization_id": "ZSNYSG3URZ",
|
||||
"canceled": false,
|
||||
"valid_from": null,
|
||||
"valid_until": null,
|
||||
"blocked": null,
|
||||
"voucher_budget_use": null
|
||||
},
|
||||
"cartposition": null,
|
||||
"voucher": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param subevent_id: The ``id`` field of the subevent to fetch
|
||||
:param id: The ``id`` field of the seat to fetch
|
||||
:query string expand: If you pass ``"orderposition"``, ``"cartposition"``, or ``"voucher"``, the respective field will be
|
||||
shown as a nested value instead of just an ID. This requires permission to access that object.
|
||||
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
|
||||
matching easier, and won't include the `seat` attribute, as that would be redundant.
|
||||
The parameter can be given multiple times.
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/seats/(id)/
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/seats/(id)/
|
||||
|
||||
Update a seat.
|
||||
|
||||
You can only change the ``blocked`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/1636/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"blocked": true
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1636,
|
||||
"subevent": null,
|
||||
"zone_name": "Ground floor",
|
||||
"row_name": "1",
|
||||
"row_label": null,
|
||||
"seat_number": "4",
|
||||
"seat_label": null,
|
||||
"seat_guid": "6c0e29e5-05d6-421f-99f3-afd01478ecad",
|
||||
"product": 104,
|
||||
"blocked": true,
|
||||
"orderposition": null,
|
||||
"cartposition": null,
|
||||
"voucher": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param subevent_id: The ``id`` field of the subevent to modify
|
||||
:param id: The ``id`` field of the seat to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The seat could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer or event does not exist **or** you have no permission to change this resource.
|
||||
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.
|
||||
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/seats/bulk_block/
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/seats/bulk_block/
|
||||
|
||||
Set the ``blocked`` attribute to ``true`` for a large number of seats at once.
|
||||
You can pass either a list of ``id`` values or a list of ``seat_guid`` values.
|
||||
You can pass up to 10,000 seats in one request.
|
||||
|
||||
The endpoint will return an error if you pass a seat ID that does not exist.
|
||||
However, it will not return an error if one of the passed seats is already blocked or sold.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/bulk_block/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"ids": [12, 45, 56]
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/bulk_block/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"seat_guids": ["6c0e29e5-05d6-421f-99f3-afd01478ecad", "c2899340-e2e7-4d05-8100-000a4b6d7cf4"]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param subevent_id: The ``id`` field of the subevent to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The seat could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer or event does not exist **or** you have no permission to change this resource.
|
||||
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/seats/bulk_unblock/
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/seats/bulk_unblock/
|
||||
|
||||
Set the ``blocked`` attribute to ``false`` for a large number of seats at once.
|
||||
You can pass either a list of ``id`` values or a list of ``seat_guid`` values.
|
||||
You can pass up to 10,000 seats in one request.
|
||||
|
||||
The endpoint will return an error if you pass a seat ID that does not exist.
|
||||
However, it will not return an error if one of the passed seat is already unblocked or is sold.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/bulk_unblock/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"ids": [12, 45, 56]
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/bulk_unblock/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"seat_guids": ["6c0e29e5-05d6-421f-99f3-afd01478ecad", "c2899340-e2e7-4d05-8100-000a4b6d7cf4"]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param subevent_id: The ``id`` field of the subevent to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The seat could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer or event does not exist **or** you have no permission to change this resource.
|
||||
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.
|
||||
@@ -1,12 +1,10 @@
|
||||
Scheduled email rules
|
||||
Automated email rules
|
||||
=====================
|
||||
|
||||
This feature requires the bundled ``pretix.plugins.sendmail`` plugin to be active for the event in order to work properly.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Scheduled email rules that specify emails that the system will send automatically at a specific point in time, e.g.
|
||||
Automated email rules that specify emails that the system will send automatically at a specific point in time, e.g.
|
||||
the day of the event.
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
@@ -25,14 +23,10 @@ limit_products list of integers List of product
|
||||
restrict_to_status list List of order states to restrict recipients to. Valid
|
||||
entries are ``p`` for paid, ``e`` for expired, ``c`` for canceled,
|
||||
``n__pending_approval`` for pending approval,
|
||||
``n__not_pending_approval_and_not_valid_if_pending`` for payment
|
||||
pending, ``n__valid_if_pending`` for payment pending but already confirmed,
|
||||
``n__not_pending_approval_and_not_valid_if_pending`` for payment pending,
|
||||
``n__valid_if_pending`` for payment pending but already confirmed,
|
||||
and ``n__pending_overdue`` for pending with payment overdue.
|
||||
The default is ``["p", "n__valid_if_pending"]``.
|
||||
checked_in_status string Check-in status to restrict recipients to. Valid strings are:
|
||||
``null`` for no filtering (default), ``checked_in`` for
|
||||
limiting to attendees that are or have been checked in, and
|
||||
``no_checkin`` for limiting to attendees who have not checked in.
|
||||
date_is_absolute boolean If ``true``, the email is set at a specific point in time.
|
||||
send_date datetime If ``date_is_absolute`` is set: Date and time to send the email.
|
||||
send_offset_days integer If ``date_is_absolute`` is not set, this is the number of days
|
||||
@@ -50,7 +44,6 @@ send_to string Can be ``"order
|
||||
or ``"both"``.
|
||||
date. Otherwise it is relative to the event start date.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 2023.7
|
||||
|
||||
The ``include_pending`` field has been deprecated.
|
||||
@@ -96,7 +89,6 @@ Endpoints
|
||||
"n__not_pending_approval_and_not_valid_if_pending",
|
||||
"n__valid_if_pending"
|
||||
],
|
||||
"checked_in_status": null,
|
||||
"send_date": null,
|
||||
"send_offset_days": 1,
|
||||
"send_offset_time": "18:00",
|
||||
@@ -147,7 +139,6 @@ Endpoints
|
||||
"n__not_pending_approval_and_not_valid_if_pending",
|
||||
"n__valid_if_pending"
|
||||
],
|
||||
"checked_in_status": null,
|
||||
"send_date": null,
|
||||
"send_offset_days": 1,
|
||||
"send_offset_time": "18:00",
|
||||
@@ -189,7 +180,6 @@ Endpoints
|
||||
"n__not_pending_approval_and_not_valid_if_pending",
|
||||
"n__valid_if_pending"
|
||||
],
|
||||
"checked_in_status": "checked_in",
|
||||
"send_date": null,
|
||||
"send_offset_days": 1,
|
||||
"send_offset_time": "18:00",
|
||||
@@ -219,7 +209,6 @@ Endpoints
|
||||
"n__not_pending_approval_and_not_valid_if_pending",
|
||||
"n__valid_if_pending"
|
||||
],
|
||||
"checked_in_status": "checked_in",
|
||||
"send_date": null,
|
||||
"send_offset_days": 1,
|
||||
"send_offset_time": "18:00",
|
||||
@@ -277,7 +266,6 @@ Endpoints
|
||||
"n__not_pending_approval_and_not_valid_if_pending",
|
||||
"n__valid_if_pending"
|
||||
],
|
||||
"checked_in_status": "checked_in",
|
||||
"send_date": null,
|
||||
"send_offset_days": 1,
|
||||
"send_offset_time": "18:00",
|
||||
|
||||
@@ -68,10 +68,6 @@ last_modified datetime Last modificati
|
||||
The ``date_from_before``, ``date_from_after``, ``date_to_before``, and ``date_to_after`` query parameters have been
|
||||
added.
|
||||
|
||||
.. versionchanged:: 2023.8.0
|
||||
|
||||
For the organizer-wide endpoint, the ``search`` query parameter has been modified to filter sub-events by their parent events slug too.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -136,7 +132,6 @@ Endpoints
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query is_public: If set to ``true``/``false``, only subevents with a matching value of ``is_public`` are returned.
|
||||
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
|
||||
@@ -468,7 +463,6 @@ Endpoints
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query is_public: If set to ``true``/``false``, only subevents with a matching value of ``is_public`` are returned.
|
||||
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
|
||||
:query event__live: If set to ``true``/``false``, only events with a matching value of ``live`` on the parent event are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
@@ -478,7 +472,6 @@ Endpoints
|
||||
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
|
||||
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||
:query search: Only return events matching a given search query.
|
||||
:query sales_channel: If set to a sales channel identifier, the response will only contain subevents from events available on this sales channel.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
.. spelling:word-list::
|
||||
|
||||
EN16931
|
||||
DSFinV-K
|
||||
|
||||
.. _rest-taxrules:
|
||||
|
||||
Tax rules
|
||||
@@ -23,12 +18,10 @@ id integer Internal ID of
|
||||
name multi-lingual string The tax rules' name
|
||||
internal_name string An optional name that is only used in the backend
|
||||
rate decimal (string) Tax rate in percent
|
||||
code string Codified reason for tax rate (or ``null``), see :ref:`rest-taxcodes`.
|
||||
price_includes_tax boolean If ``true`` (default), tax is assumed to be included in
|
||||
the specified product price
|
||||
eu_reverse_charge boolean **DEPRECATED**. If ``true``, EU reverse charge rules
|
||||
are applied. Will be ignored if custom rules are set.
|
||||
Use custom rules instead.
|
||||
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied. Will
|
||||
be ignored if custom rules are set.
|
||||
home_country string Merchant country (required for reverse charge), can be
|
||||
``null`` or empty string
|
||||
keep_gross_if_rate_changes boolean If ``true``, changes of the tax rate based on custom
|
||||
@@ -48,42 +41,6 @@ custom_rules object Dynamic rules s
|
||||
|
||||
The ``custom_rules`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2023.8
|
||||
|
||||
The ``code`` attribute has been added.
|
||||
|
||||
.. _rest-taxcodes:
|
||||
|
||||
Tax codes
|
||||
---------
|
||||
|
||||
For integration with external systems, such as electronic invoicing or bookkeeping systems, the tax rate itself is often
|
||||
not sufficient information. For example, there could be many different reasons why a sale has a tax rate of 0 %, but the
|
||||
external handling of the transaction depends on which reason applies. Therefore, pretix allows to supply a codified
|
||||
reason that allows us to understand what the specific legal situation is. These tax codes are modeled after a combination
|
||||
of the code lists from the European standard EN16931 and the German standard DSFinV-K.
|
||||
|
||||
The following codes are supported:
|
||||
|
||||
- ``S/standard`` -- Standard VAT rate in the merchant country
|
||||
- ``S/reduced`` -- Reduced VAT rate in the merchant country
|
||||
- ``S/averaged`` -- Averaged VAT rate in the merchant country (known use case: agricultural businesses in Germany)
|
||||
- ``AE`` -- Reverse charge
|
||||
- ``O`` -- Services outside of scope of tax
|
||||
- ``E`` -- Exempt from tax (no reason given)
|
||||
- ``E/<reason>`` -- Exempt from tax, where ``<reason>`` is one of the codes listed in the `VATEX code list`_ version 5.0.
|
||||
- ``Z`` -- Zero-rated goods
|
||||
- ``G`` -- Free export item, VAT not charged
|
||||
- ``K`` -- VAT exempt for EEA intra-community supply of goods and services
|
||||
- ``L`` -- Canary Islands general indirect tax
|
||||
- ``M`` -- Tax for production, services and importation in Ceuta and Melilla
|
||||
- ``B`` -- Transferred (VAT), only in Italy
|
||||
|
||||
The code set in the ``code`` attribute of the tax rule is used by default. When ``eu_reverse_charge`` is active, the
|
||||
code is replaced by ``AE`` for reverse charge sales and by ``O`` for non-EU sales. When configuring custom rules, you
|
||||
should actively set a ``"code"`` key on each rule. Only for ``"action": "reverse"`` we automatically apply the code
|
||||
``AE``, in all other cases the default ``code`` of the tax rule is selected.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -116,7 +73,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"internal_name": "VAT",
|
||||
"code": "S/standard",
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
@@ -158,7 +114,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"internal_name": "VAT",
|
||||
"code": "S/standard",
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
@@ -208,7 +163,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"internal_name": "VAT",
|
||||
"code": "S/standard",
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
@@ -257,7 +211,6 @@ Endpoints
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"internal_name": "VAT",
|
||||
"code": "S/standard",
|
||||
"rate": "20.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
@@ -304,4 +257,3 @@ Endpoints
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this tax rule cannot be deleted since it is currently in use.
|
||||
|
||||
.. _here: https://github.com/pretix/pretix/blob/master/src/pretix/static/schema/tax-rules-custom.schema.json
|
||||
.. _VATEX code list: https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/Registry+of+supporting+artefacts+to+implement+EN16931#RegistryofsupportingartefactstoimplementEN16931-Codelists
|
||||
@@ -22,8 +22,6 @@ id integer Internal ID of
|
||||
name string Team name
|
||||
all_events boolean Whether this team has access to all events
|
||||
limit_events list List of event slugs this team has access to
|
||||
require_2fa boolean Whether members of this team are required to use
|
||||
two-factor authentication
|
||||
can_create_events boolean
|
||||
can_change_teams boolean
|
||||
can_change_organizer_settings boolean
|
||||
@@ -124,7 +122,6 @@ Team endpoints
|
||||
"name": "Admin team",
|
||||
"all_events": true,
|
||||
"limit_events": [],
|
||||
"require_2fa": true,
|
||||
"can_create_events": true,
|
||||
...
|
||||
}
|
||||
@@ -162,7 +159,6 @@ Team endpoints
|
||||
"name": "Admin team",
|
||||
"all_events": true,
|
||||
"limit_events": [],
|
||||
"require_2fa": true,
|
||||
"can_create_events": true,
|
||||
...
|
||||
}
|
||||
@@ -190,7 +186,6 @@ Team endpoints
|
||||
"name": "Admin team",
|
||||
"all_events": true,
|
||||
"limit_events": [],
|
||||
"require_2fa": true,
|
||||
"can_create_events": true,
|
||||
...
|
||||
}
|
||||
@@ -208,7 +203,6 @@ Team endpoints
|
||||
"name": "Admin team",
|
||||
"all_events": true,
|
||||
"limit_events": [],
|
||||
"require_2fa": true,
|
||||
"can_create_events": true,
|
||||
...
|
||||
}
|
||||
@@ -252,7 +246,6 @@ Team endpoints
|
||||
"name": "Admin team",
|
||||
"all_events": true,
|
||||
"limit_events": [],
|
||||
"require_2fa": true,
|
||||
"can_create_events": true,
|
||||
...
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.order.modified``
|
||||
* ``pretix.event.order.contact.changed``
|
||||
* ``pretix.event.order.changed.*``
|
||||
* ``pretix.event.order.deleted`` (can only occur for test mode orders)
|
||||
* ``pretix.event.order.refund.created``
|
||||
* ``pretix.event.order.refund.created.externally``
|
||||
* ``pretix.event.order.refund.requested``
|
||||
@@ -68,9 +67,6 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.live.deactivated``
|
||||
* ``pretix.event.testmode.activated``
|
||||
* ``pretix.event.testmode.deactivated``
|
||||
* ``pretix.customer.created``
|
||||
* ``pretix.customer.changed``
|
||||
* ``pretix.customer.anonymized``
|
||||
|
||||
Installed plugins might register more valid values.
|
||||
|
||||
@@ -116,7 +112,6 @@ Endpoints
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean enabled: Only show webhooks that are or are not enabled
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
14
doc/conf.py
@@ -69,7 +69,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'pretix'
|
||||
copyright = '2014-{}, rami.io GmbH'.format(date.today().year)
|
||||
copyright = '2014-{}, Raphael Michel'.format(date.today().year)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -233,8 +233,8 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'pretix.tex', 'pretix Developer Documentation',
|
||||
'rami.io GmbH', 'manual'),
|
||||
('index', 'pretix.tex', 'pretix Documentation',
|
||||
'Raphael Michel', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -263,8 +263,8 @@ latex_documents = [
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'pretix', 'pretix Developer Documentation',
|
||||
['rami.io GmbH'], 1)
|
||||
('index', 'pretix', 'pretix Documentation',
|
||||
['Raphael Michel'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
@@ -277,8 +277,8 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'pretix', 'pretix Developer Documentation',
|
||||
'rami.io GmbH', 'pretix', 'One line description of project.',
|
||||
('index', 'pretix', 'pretix Documentation',
|
||||
'Raphael Michel', 'pretix', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ Table of contents
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
user/index
|
||||
admin/index
|
||||
api/index
|
||||
development/index
|
||||
plugins/index
|
||||
license/faq
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ First, you need to declare that you are using non-essential cookies by respondin
|
||||
signal:
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:no-index:
|
||||
:members: register_cookie_providers
|
||||
|
||||
You are expected to return a list of ``CookieProvider`` objects instantiated from the following class:
|
||||
|
||||
@@ -11,10 +11,9 @@ Core
|
||||
----
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: periodic_task, event_live_issues, event_copy_data, email_filter, register_notification_types, notification,
|
||||
item_copy_data, register_sales_channel_types, register_global_settings, quota_availability, global_email_filter,
|
||||
register_ticket_secret_generators, gift_card_transaction_display,
|
||||
register_text_placeholders, register_mail_placeholders, device_info_updated
|
||||
:members: periodic_task, event_live_issues, event_copy_data, email_filter, register_notification_types,
|
||||
item_copy_data, register_sales_channels, register_global_settings, quota_availability, global_email_filter,
|
||||
register_ticket_secret_generators, gift_card_transaction_display
|
||||
|
||||
Order events
|
||||
""""""""""""
|
||||
@@ -22,14 +21,12 @@ Order events
|
||||
There are multiple signals that will be sent out in the ordering cycle:
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: validate_cart, validate_cart_addons, validate_order, order_valid_if_pending, order_fee_calculation, order_paid, order_placed, order_canceled, order_reactivated, order_expired, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download, order_split, order_gracefully_delete, invoice_line_text
|
||||
|
||||
Check-ins
|
||||
"""""""""
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: checkin_created
|
||||
|
||||
|
||||
@@ -37,25 +34,22 @@ Frontend
|
||||
--------
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head
|
||||
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, sass_preamble, sass_postamble, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header
|
||||
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:no-index:
|
||||
:members: order_info, order_info_top, order_meta_from_request, order_api_meta_from_request
|
||||
:members: order_info, order_info_top, order_meta_from_request
|
||||
|
||||
Request flow
|
||||
""""""""""""
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:no-index:
|
||||
:members: process_request, process_response
|
||||
|
||||
Vouchers
|
||||
""""""""
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:no-index:
|
||||
:members: voucher_redeem_info
|
||||
|
||||
Backend
|
||||
@@ -67,28 +61,24 @@ Backend
|
||||
item_formsets, order_search_filter_q, order_search_forms
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: logentry_display, logentry_object_link, requiredaction_display, timeline_events, orderposition_blocked_display, customer_created, customer_signed_in
|
||||
|
||||
Vouchers
|
||||
""""""""
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:no-index:
|
||||
:members: item_forms, voucher_form_class, voucher_form_html, voucher_form_validation
|
||||
|
||||
Dashboards
|
||||
""""""""""
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:no-index:
|
||||
:members: event_dashboard_widgets, user_dashboard_widgets, event_dashboard_top
|
||||
|
||||
Ticket designs
|
||||
""""""""""""""
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: layout_text_variables, layout_image_variables
|
||||
|
||||
.. automodule:: pretix.plugins.ticketoutputpdf.signals
|
||||
@@ -98,9 +88,4 @@ API
|
||||
---
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: validate_event_settings, api_event_settings_fields
|
||||
|
||||
.. automodule:: pretix.api.signals
|
||||
:no-index:
|
||||
:members: register_device_security_profile, order_api_details, orderposition_api_details
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
|
||||
.. _`importcol`:
|
||||
|
||||
Extending the import process
|
||||
============================
|
||||
Extending the order import process
|
||||
==================================
|
||||
|
||||
It's possible through the backend to import objects into pretix, for example orders from a legacy ticketing system. If
|
||||
your plugin defines additional data structures around those objects, it might be useful to make it possible to import
|
||||
them as well.
|
||||
It's possible through the backend to import orders into pretix, for example from a legacy ticketing system. If your
|
||||
plugins defines additional data structures around orders, it might be useful to make it possible to import them as well.
|
||||
|
||||
Import process
|
||||
--------------
|
||||
@@ -41,7 +40,7 @@ Column registration
|
||||
|
||||
The import API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available import columns. Your plugin
|
||||
should listen for this signal and return the subclass of ``pretix.base.modelimport.ImportColumn``
|
||||
should listen for this signal and return the subclass of ``pretix.base.orderimport.ImportColumn``
|
||||
that we'll provide in this plugin:
|
||||
|
||||
.. sourcecode:: python
|
||||
@@ -57,17 +56,10 @@ that we'll provide in this plugin:
|
||||
EmailColumn(sender),
|
||||
]
|
||||
|
||||
Similar signals exist for other objects:
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: voucher_import_columns
|
||||
|
||||
|
||||
The column class API
|
||||
--------------------
|
||||
|
||||
.. class:: pretix.base.modelimport.ImportColumn
|
||||
.. class:: pretix.base.orderimport.ImportColumn
|
||||
|
||||
The central object of each import extension is the subclass of ``ImportColumn``.
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Writing a template placeholder plugin
|
||||
=====================================
|
||||
Writing an e-mail placeholder plugin
|
||||
====================================
|
||||
|
||||
A template placeholder is a dynamic value that pretix users can use in their email templates and in other
|
||||
configurable texts.
|
||||
An email placeholder is a dynamic value that pretix users can use in their email templates.
|
||||
|
||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
||||
|
||||
@@ -13,31 +12,31 @@ Placeholder registration
|
||||
------------------------
|
||||
|
||||
The placeholder API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available placeholders. Your plugin
|
||||
should listen for this signal and return an instance of a subclass of ``pretix.base.services.placeholders.BaseTextPlaceholder``:
|
||||
does use a signal to get a list of all available email placeholders. Your plugin
|
||||
should listen for this signal and return an instance of a subclass of ``pretix.base.email.BaseMailTextPlaceholder``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_text_placeholders
|
||||
from pretix.base.signals import register_mail_placeholders
|
||||
|
||||
|
||||
@receiver(register_text_placeholders, dispatch_uid="placeholder_custom")
|
||||
def register_placeholder_renderers(sender, **kwargs):
|
||||
from .placeholders import MyPlaceholderClass
|
||||
@receiver(register_mail_placeholders, dispatch_uid="placeholder_custom")
|
||||
def register_mail_renderers(sender, **kwargs):
|
||||
from .email import MyPlaceholderClass
|
||||
return MyPlaceholder()
|
||||
|
||||
|
||||
Context mechanism
|
||||
-----------------
|
||||
|
||||
Templates are used in different "contexts" within pretix. For example, many emails are rendered from
|
||||
templates in the context of an order, but some are not, such as the notification of a waiting list voucher.
|
||||
Emails are sent in different "contexts" within pretix. For example, many emails are sent in the
|
||||
the context of an order, but some are not, such as the notification of a waiting list voucher.
|
||||
|
||||
Not all placeholders make sense everywhere, and placeholders usually depend on some parameters
|
||||
Not all placeholders make sense in every email, and placeholders usually depend some parameters
|
||||
themselves, such as the ``Order`` object. Therefore, placeholders are expected to explicitly declare
|
||||
what values they depend on and they will only be available in a context where all those dependencies are
|
||||
what values they depend on and they will only be available in an email if all those dependencies are
|
||||
met. Currently, placeholders can depend on the following context parameters:
|
||||
|
||||
* ``event``
|
||||
@@ -52,7 +51,7 @@ There are a few more that are only to be used internally but not by plugins.
|
||||
The placeholder class
|
||||
---------------------
|
||||
|
||||
.. class:: pretix.base.services.placeholders.BaseTextPlaceholder
|
||||
.. class:: pretix.base.email.BaseMailTextPlaceholder
|
||||
|
||||
.. autoattribute:: identifier
|
||||
|
||||
@@ -78,18 +77,7 @@ functions:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
placeholder = SimpleFunctionalTextPlaceholder(
|
||||
placeholder = SimpleFunctionalMailTextPlaceholder(
|
||||
'code', ['order'], lambda order: order.code, sample='F8VVL'
|
||||
)
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: register_text_placeholders
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:no-index:
|
||||
:members: register_mail_placeholders
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ This will automatically make pretix discover this plugin as soon as it is instal
|
||||
through ``pip``. During development, you can just run ``python setup.py develop`` inside
|
||||
your plugin source directory to make it discoverable.
|
||||
|
||||
.. _`signals`:
|
||||
Signals
|
||||
-------
|
||||
|
||||
@@ -154,25 +153,6 @@ in the ``installed`` method:
|
||||
Note that ``installed`` will *not* be called if the plugin is indirectly activated for an event
|
||||
because the event is created with settings copied from another event.
|
||||
|
||||
.. _`registries`:
|
||||
Registries
|
||||
----------
|
||||
|
||||
Many signals in pretix are used so that plugins can "register" a class, e.g. a payment provider or a
|
||||
ticket renderer.
|
||||
|
||||
However, for some of them (types of :ref:`Log Entries <logging>`) we use a different method to keep track of them:
|
||||
In a ``Registry``, classes are collected at application startup, along with a unique key (in case
|
||||
of LogEntryType, the ``action_type``) as well as which plugin registered them.
|
||||
|
||||
To register a class, you can use one of several decorators provided by the Registry object:
|
||||
|
||||
.. autoclass:: pretix.base.logentrytypes.LogEntryTypeRegistry
|
||||
:members: register, new, new_from_dict
|
||||
|
||||
All files in which classes are registered need to be imported in the ``AppConfig.ready`` as explained
|
||||
in `Signals <signals>`_ above.
|
||||
|
||||
Views
|
||||
-----
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ The project pretix is split into several components. The main components are:
|
||||
create and manage their events, items, orders and tickets.
|
||||
|
||||
**presale**
|
||||
This is the ticket shop itself, containing all of the parts visible to the
|
||||
This is the ticket-shop itself, containing all of the parts visible to the
|
||||
end user. Also called "frontend" in parts of this documentation.
|
||||
|
||||
**api**
|
||||
|
||||
@@ -37,7 +37,7 @@ you to execute a piece of code with a different locale:
|
||||
This is very useful e.g. when sending an email to a user that has a different language than the user performing the
|
||||
action that causes the mail to be sent.
|
||||
|
||||
.. _translation features: https://docs.djangoproject.com/en/4.2/topics/i18n/translation/
|
||||
.. _translation features: https://docs.djangoproject.com/en/1.9/topics/i18n/translation/
|
||||
.. _GNU gettext: https://www.gnu.org/software/gettext/
|
||||
.. _strings: https://django-i18nfield.readthedocs.io/en/latest/strings.html
|
||||
.. _database fields: https://django-i18nfield.readthedocs.io/en/latest/quickstart.html
|
||||
|
||||
@@ -18,5 +18,3 @@ Contents:
|
||||
email
|
||||
permissions
|
||||
logging
|
||||
locking
|
||||
timemachine
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
.. highlight:: python
|
||||
|
||||
Resource locking
|
||||
================
|
||||
|
||||
.. versionchanged:: 2023.8
|
||||
|
||||
Our locking mechanism changed heavily in version 2023.8. Read `this PR`_ for background information.
|
||||
|
||||
One of pretix's core objectives as a ticketing system could be described as the management of scarce resources.
|
||||
Specifically, the following types of scarce-ness exist in pretix:
|
||||
|
||||
- Quotas can limit the number of tickets available
|
||||
- Seats can only be booked once
|
||||
- Vouchers can only be used a limited number of times
|
||||
- Some memberships can only be used a limited number of times
|
||||
|
||||
For all of these, it is critical that we prevent race conditions.
|
||||
While for some events it wouldn't be a big deal to sell a ticket more or less, for some it would be problematic and selling the same seat twice would always be catastrophic.
|
||||
|
||||
We therefore implement a standardized locking approach across the system to limit concurrency in cases where it could
|
||||
be problematic.
|
||||
|
||||
To acquire a lock on a set of quotas to create a new order that uses that quota, you should follow the following pattern::
|
||||
|
||||
with transaction.atomic(durable=True):
|
||||
quotas = Quota.objects.filter(...)
|
||||
lock_objects(quotas, shared_lock_objects=[event])
|
||||
check_quota(quotas)
|
||||
create_ticket()
|
||||
|
||||
The lock will automatically be released at the end of your database transaction.
|
||||
|
||||
Generally, follow the following guidelines during your development:
|
||||
|
||||
- **Always** acquire a lock on every **quota**, **voucher** or **seat** that you "use" during your transaction. "Use"
|
||||
here means any action after which the quota, voucher or seat will be **less available**, such as creating a cart
|
||||
position, creating an order, creating a blocking voucher, etc.
|
||||
|
||||
- There is **no need** to acquire a lock if you **free up** capacity, e.g. by canceling an order, deleting a voucher, etc.
|
||||
|
||||
- **Always** acquire a shared lock on the ``event`` you are working in whenever you acquire a lock on a quota, voucher,
|
||||
or seat.
|
||||
|
||||
- Only call ``lock_objects`` **once** per transaction. If you violate this rule, `deadlocks`_ become possible.
|
||||
|
||||
- For best performance, call ``lock_objects`` as **late** in your transaction as possible, but always before you check
|
||||
if the desired resource is still available in sufficient quantity.
|
||||
|
||||
Behind the scenes, the locking is implemented through `PostgreSQL advisory locks`_. You should also be aware of the following
|
||||
properties of our system:
|
||||
|
||||
- In some situations, an exclusive lock on the ``event`` is used, such as when the system can't determine for sure which
|
||||
seats will become unavailable after the transaction.
|
||||
|
||||
- An exclusive lock on the event is also used if you pass more than 20 objects to ``lock_objects``. This is a performance
|
||||
trade-off because it would take long to acquire all of the individual locks.
|
||||
|
||||
- If ``lock_objects`` is unable to acquire a lock within 3 seconds, a ``LockTimeoutException`` will be thrown.
|
||||
|
||||
.. note::
|
||||
|
||||
We currently do not use ``lock_objects`` for memberships. Instead, we use ``select_for_update()`` on the membership
|
||||
model. This might change in the future, but you should usually not be concerned about it since
|
||||
``validate_memberships_in_order(lock=True)`` will handle it for you.
|
||||
|
||||
.. _this PR: https://github.com/pretix/pretix/pull/2408
|
||||
.. _deadlocks: https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS
|
||||
.. _PostgreSQL advisory locks: https://www.postgresql.org/docs/11/explicit-locking.html#ADVISORY-LOCKS
|
||||
@@ -20,8 +20,7 @@ To actually log an action, you can just call the ``log_action`` method on your o
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
order.log_action('pretix.event.order.comment', user=user,
|
||||
data={"new_comment": "Hello, world."})
|
||||
order.log_action('pretix.event.order.canceled', user=user, data={})
|
||||
|
||||
The positional ``action`` argument should represent the type of action and should be globally unique, we
|
||||
recommend to prefix it with your package name, e.g. ``paypal.payment.rejected``. The ``user`` argument is
|
||||
@@ -73,101 +72,24 @@ following ready-to-include template::
|
||||
{% include "pretixcontrol/includes/logs.html" with obj=order %}
|
||||
|
||||
We now need a way to translate the action codes like ``pretix.event.changed`` into human-readable
|
||||
strings. The :py:attr:`pretix.base.logentrytypes.log_entry_types` :ref:`registry <registries>` allows you to do so. A simple
|
||||
strings. The :py:attr:`pretix.base.signals.logentry_display` signals allows you to do so. A simple
|
||||
implementation could look like:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
from pretix.base.logentrytypes import log_entry_types
|
||||
|
||||
|
||||
@log_entry_types.new_from_dict({
|
||||
'pretix.event.order.comment': _('The order\'s internal comment has been updated to: {new_comment}'),
|
||||
'pretix.event.order.paid': _('The order has been marked as paid.'),
|
||||
# ...
|
||||
})
|
||||
class CoreOrderLogEntryType(OrderLogEntryType):
|
||||
pass
|
||||
|
||||
Please note that you always need to define your own inherited ``LogEntryType`` class in your plugin. If you would just
|
||||
register an instance of a ``LogEntryType`` class defined in pretix core, it cannot be automatically detected as belonging
|
||||
to your plugin, leading to confusing user interface situations.
|
||||
|
||||
|
||||
Customizing log entry display
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
The base ``LogEntryType`` classes allow for varying degree of customization in their descendants.
|
||||
|
||||
If you want to add another log message for an existing core object (e.g. an :class:`Order <pretix.base.models.Order>`,
|
||||
:class:`Item <pretix.base.models.Item>`, or :class:`Voucher <pretix.base.models.Voucher>`), you can inherit
|
||||
from its predefined :class:`LogEntryType <pretix.base.logentrytypes.LogEntryType>`, e.g.
|
||||
:class:`OrderLogEntryType <pretix.base.logentrytypes.OrderLogEntryType>`, and just specify a new plaintext string.
|
||||
You can use format strings to insert information from the LogEntry's `data` object as shown in the section above.
|
||||
|
||||
If you define a new model object in your plugin, you should make sure proper object links in the user interface are
|
||||
displayed for it. If your model object belongs logically to a pretix :class:`Event <pretix.base.models.Event>`, you can inherit from :class:`EventLogEntryType <pretix.base.logentrytypes.EventLogEntryType>`,
|
||||
and set the ``object_link_*`` fields accordingly. ``object_link_viewname`` refers to a django url name, which needs to
|
||||
accept the arguments `organizer` and `event`, containing the respective slugs, and additional arguments provided by
|
||||
``object_link_args``. The default implementation of ``object_link_args`` will return an argument named by
|
||||
````object_link_argname``, with a value of ``content_object.pk`` (the primary key of the model object).
|
||||
If you want to customize the name displayed for the object (instead of the result of calling ``str()`` on it),
|
||||
overwrite ``object_link_display_name``.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class ItemLogEntryType(EventLogEntryType):
|
||||
object_link_wrapper = _('Product {val}')
|
||||
|
||||
# link will be generated as reverse('control:event.item', {'organizer': ..., 'event': ..., 'item': item.pk})
|
||||
object_link_viewname = 'control:event.item'
|
||||
object_link_argname = 'item'
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class OrderLogEntryType(EventLogEntryType):
|
||||
object_link_wrapper = _('Order {val}')
|
||||
|
||||
# link will be generated as reverse('control:event.order', {'organizer': ..., 'event': ..., 'code': order.code})
|
||||
object_link_viewname = 'control:event.order'
|
||||
|
||||
def object_link_args(self, order):
|
||||
return {'code': order.code}
|
||||
|
||||
def object_link_display_name(self, order):
|
||||
return order.code
|
||||
|
||||
To show more sophisticated message strings, e.g. varying the message depending on information from the :class:`LogEntry <pretix.base.models.log.LogEntry>`'s
|
||||
`data` object, override the `display` method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@log_entry_types.new()
|
||||
class PaypalEventLogEntryType(EventLogEntryType):
|
||||
action_type = 'pretix.plugins.paypal.event'
|
||||
|
||||
def display(self, logentry):
|
||||
event_type = logentry.parsed_data.get('event_type')
|
||||
text = {
|
||||
'PAYMENT.SALE.COMPLETED': _('Payment completed.'),
|
||||
'PAYMENT.SALE.DENIED': _('Payment denied.'),
|
||||
# ...
|
||||
}.get(event_type, f"({event_type})")
|
||||
return _('PayPal reported an event: {}').format(text)
|
||||
|
||||
.. automethod:: pretix.base.logentrytypes.LogEntryType.display
|
||||
|
||||
If your new model object does not belong to an :class:`Event <pretix.base.models.Event>`, you need to inherit directly from ``LogEntryType`` instead
|
||||
of ``EventLogEntryType``, providing your own implementation of ``get_object_link_info`` if object links should be
|
||||
displayed.
|
||||
|
||||
.. autoclass:: pretix.base.logentrytypes.LogEntryType
|
||||
:members: get_object_link_info
|
||||
|
||||
from pretix.base.signals import logentry_display
|
||||
|
||||
@receiver(signal=logentry_display)
|
||||
def pretixcontrol_logentry_display(sender, logentry, **kwargs):
|
||||
plains = {
|
||||
'pretix.event.order.paid': _('The order has been marked as paid.'),
|
||||
'pretix.event.order.refunded': _('The order has been refunded.'),
|
||||
'pretix.event.order.canceled': _('The order has been canceled.'),
|
||||
...
|
||||
}
|
||||
if logentry.action_type in plains:
|
||||
return plains[logentry.action_type]
|
||||
|
||||
Sending notifications
|
||||
---------------------
|
||||
|
||||
@@ -15,7 +15,7 @@ includes serializers for serializing the following types:
|
||||
* Built-in types: ``int``, ``float``, ``decimal.Decimal``, ``dict``, ``list``, ``bool``
|
||||
* ``datetime.date``, ``datetime.datetime``, ``datetime.time``
|
||||
* ``LazyI18nString``
|
||||
* References to Django ``File`` objects that are already stored in a storage backend [#f1]_
|
||||
* References to Django ``File`` objects that are already stored in a storage backend
|
||||
* References to model instances
|
||||
|
||||
In code, we recommend to always use the ``.get()`` method on the settings object to access a value, but for
|
||||
@@ -55,9 +55,6 @@ You can simply use it like this:
|
||||
"preserve his reservation."),
|
||||
)
|
||||
|
||||
|
||||
.. _settings-defaults-in-plugins:
|
||||
|
||||
Defaults in plugins
|
||||
-------------------
|
||||
|
||||
@@ -73,9 +70,3 @@ Make sure that you include this code in a module that is imported at app loading
|
||||
|
||||
.. _django-hierarkey: https://github.com/raphaelm/django-hierarkey
|
||||
.. _documentation: https://django-hierarkey.readthedocs.io/en/latest/
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#f1] If you store ``File`` instances in per-event settings, make sure to always register them with ``add_default``
|
||||
as described above in :ref:`settings-defaults-in-plugins`. Otherwise, the file won't get copied properly if the
|
||||
user copies the settings of an existing event to a new one.
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
Time machine mode
|
||||
=================
|
||||
|
||||
In test mode, pretix provides a "time machine" feature which allows event organizers
|
||||
to test their shop as if it were a different date and time. To enable this feature, they can
|
||||
click on the "time machine"-link in the test mode warning box on the event page.
|
||||
|
||||
Internally, this time machine mode is implemented by calling our custom :py:meth:`time_machine_now()`
|
||||
function instead of :py:meth:`django.utils.timezone.now()` in all places where the fake time should be
|
||||
taken into account. If you add code that uses the current date and time for checking whether some
|
||||
product can be bought, you should use :py:meth:`time_machine_now`.
|
||||
|
||||
.. autofunction:: pretix.base.timemachine.time_machine_now
|
||||
|
||||
Background tasks
|
||||
----------------
|
||||
|
||||
The time machine datetime is passed through the request flow via a thread-local variable (ContextVar).
|
||||
Therefore, if you call a background task in the order process, where time_machine_now should be
|
||||
respected, you need to pass it through manually as shown in the example below:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.task()
|
||||
def my_task(self, override_now_dt: datetime=None) -> None:
|
||||
with time_machine_now_assigned(override_now_dt):
|
||||
# ...do something that uses time_machine_now()
|
||||
|
||||
my_task.apply_async(kwargs={'override_now_dt': time_machine_now(default=None)})
|
||||
|
||||
|
||||
.. autofunction:: pretix.base.timemachine.time_machine_now_assigned
|
||||
@@ -15,33 +15,25 @@ and the admin panel is available at ``https://pretix.eu/control/event/bigorg/awe
|
||||
|
||||
If the organizer now configures a custom domain like ``tickets.bigorg.com``, his event will
|
||||
from now on be available on ``https://tickets.bigorg.com/awesomecon/``. The former URL at
|
||||
``pretix.eu`` will redirect there. It's also possible to do this for just an event, in which
|
||||
case the event will be available on ``https://tickets.awesomecon.org/``.
|
||||
|
||||
However, the admin panel will still only be available on ``pretix.eu`` for convenience and security reasons.
|
||||
``pretix.eu`` will redirect there. However, the admin panel will still only be available
|
||||
on ``pretix.eu`` for convenience and security reasons.
|
||||
|
||||
URL routing
|
||||
-----------
|
||||
|
||||
The hard part about implementing this URL routing in Django is that
|
||||
``https://pretix.eu/bigorg/awesomecon/`` contains two parameters of nearly arbitrary content
|
||||
and ``https://tickets.bigorg.com/awesomecon/`` contains only one and ``https://tickets.awesomecon.org/`` does not contain any.
|
||||
The only robust way to do this is by having *separate* URL configuration for those three cases.
|
||||
and ``https://tickets.bigorg.com/awesomecon/`` contains only one. The only robust way to do
|
||||
this is by having *separate* URL configuration for those two cases. In pretix, we call the
|
||||
former our ``maindomain`` config and the latter our ``subdomain`` config. For pretix's core
|
||||
modules we do some magic to avoid duplicate configuration, but for a fairly simple plugin with
|
||||
only a handful of routes, we recommend just configuring the two URL sets separately.
|
||||
|
||||
In pretix, we therefore do not have a global URL configuration, but three, living in the following modules:
|
||||
|
||||
- ``pretix.multidomain.maindomain_urlconf``
|
||||
- ``pretix.multidomain.organizer_domain_urlconf``
|
||||
- ``pretix.multidomain.event_domain_urlconf``
|
||||
|
||||
We provide some helper utilities to work with these to avoid duplicate configuration of the individual URLs.
|
||||
The file ``urls.py`` inside your plugin package will be loaded and scanned for URL configuration
|
||||
automatically and should be provided by any plugin that provides any view.
|
||||
However, unlike plain Django, we look not only for a ``urlpatterns`` attribute on the module but support other
|
||||
attributes like ``event_patterns`` and ``organizer_patterns`` as well.
|
||||
|
||||
For example, for a simple plugin that adds one URL to the backend and one event-level URL to the frontend, you can
|
||||
create the following configuration in your ``urls.py``::
|
||||
A very basic example that provides one view in the admin panel and one view in the frontend
|
||||
could look like this::
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
@@ -60,7 +52,7 @@ create the following configuration in your ``urls.py``::
|
||||
As you can see, the view in the frontend is not included in the standard Django ``urlpatterns``
|
||||
setting but in a separate list with the name ``event_patterns``. This will automatically prepend
|
||||
the appropriate parameters to the regex (e.g. the event or the event and the organizer, depending
|
||||
on the called domain). For organizer-level views, ``organizer_patterns`` works the same way.
|
||||
on the called domain).
|
||||
|
||||
If you only provide URLs in the admin area, you do not need to provide a ``event_patterns`` attribute.
|
||||
|
||||
@@ -79,21 +71,12 @@ is a python method that emulates a behavior similar to ``reverse``:
|
||||
|
||||
.. autofunction:: pretix.multidomain.urlreverse.eventreverse
|
||||
|
||||
If you need to communicate the URL externally, you can use a different method to ensure that it is always an absolute URL:
|
||||
|
||||
.. autofunction:: pretix.multidomain.urlreverse.build_absolute_uri
|
||||
|
||||
In addition, there is a template tag that works similar to ``url`` but takes an event or organizer object
|
||||
as its first argument and can be used like this::
|
||||
|
||||
{% load eventurl %}
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="payment" %}">Pay</a>
|
||||
<a href="{% abseventurl request.event "presale:event.checkout" step="payment" %}">Pay</a>
|
||||
|
||||
To generate absolute URLs on the main domain, you can use the ``absurl`` template tag::
|
||||
|
||||
{% load eventurl %}
|
||||
<a href="{% absmainurl "control:event.settings" organizer=request.event.organizer.slug event=request.event.slug %}">Event settings</a>
|
||||
|
||||
Implementation details
|
||||
----------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Plugin & core development
|
||||
=========================
|
||||
Developer documentation
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
@@ -5,7 +5,7 @@ Development setup
|
||||
|
||||
This tutorial helps you to get started hacking with pretix on your own computer. You need this to
|
||||
be able to contribute to pretix, but it might also be helpful if you want to write your own plugins.
|
||||
If you want to install pretix on a server for actual usage, go to the [administrator documentation](https://docs.pretix.eu/self-hosting/) instead.
|
||||
If you want to install pretix on a server for actual usage, go to the :ref:`admindocs` instead.
|
||||
|
||||
Obtain a copy of the source code
|
||||
--------------------------------
|
||||
@@ -18,7 +18,7 @@ External Dependencies
|
||||
---------------------
|
||||
Your should install the following on your system:
|
||||
|
||||
* Python 3.9 or newer
|
||||
* Python 3.5 or newer
|
||||
* ``pip`` for Python 3 (Debian package: ``python3-pip``)
|
||||
* ``python-dev`` for Python 3 (Debian package: ``python3-dev``)
|
||||
* On Debian/Ubuntu: ``python-venv`` for Python 3 (Debian package: ``python3-venv``)
|
||||
@@ -33,7 +33,7 @@ Your should install the following on your system:
|
||||
Your local python environment
|
||||
-----------------------------
|
||||
|
||||
Please execute ``python -V`` or ``python3 -V`` to make sure you have Python 3.9
|
||||
Please execute ``python -V`` or ``python3 -V`` to make sure you have Python 3.4
|
||||
(or newer) installed. Also make sure you have pip for Python 3 installed, you can
|
||||
execute ``pip3 -V`` to check. Then use Python's internal tools to create a virtual
|
||||
environment and activate it for your current session::
|
||||
@@ -96,20 +96,6 @@ http://localhost:8000/control/ for the admin view.
|
||||
port (for example because you develop on `pretixdroid`_), you can check
|
||||
`Django's documentation`_ for more options.
|
||||
|
||||
When running the local development webserver, ensure Celery is not configured
|
||||
in ``pretix.cfg``. i.e., you should remove anything such as::
|
||||
|
||||
[celery]
|
||||
backend=redis://redis:6379/2
|
||||
broker=redis://redis:6379/2
|
||||
|
||||
If you choose to use Celery for development, you must also start a Celery worker
|
||||
process::
|
||||
|
||||
celery -A pretix.celery_app worker -l info
|
||||
|
||||
However, beware that code changes will not auto-reload within Celery.
|
||||
|
||||
.. _`checksandtests`:
|
||||
|
||||
Code checks and unit tests
|
||||
@@ -136,7 +122,9 @@ It is a good idea to put this command into your git hook ``.git/hooks/pre-commit
|
||||
for example, to check for any errors in any staged files when committing::
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
cd $GIT_DIR/../src
|
||||
export GIT_WORK_TREE=../
|
||||
export GIT_DIR=../.git
|
||||
source ../env/bin/activate # Adjust to however you activate your virtual environment
|
||||
for file in $(git diff --cached --name-only | grep -E '\.py$' | grep -Ev "migrations|mt940\.py|pretix/settings\.py|make_testdata\.py|testutils/settings\.py|tests/settings\.py|pretix/base/models/__init__\.py|.*_pb2\.py")
|
||||
do
|
||||
@@ -209,15 +197,5 @@ with the documentation a lot, you might find it useful to use sphinx-autobuild::
|
||||
Then, go to http://localhost:8081 for a version of the documentation that automatically re-builds
|
||||
whenever you change a source file.
|
||||
|
||||
Working with frontend assets
|
||||
----------------------------
|
||||
|
||||
To update the frontend styles of shops with a custom styling, run the following commands inside
|
||||
your virtual environment.::
|
||||
|
||||
python -m pretix collectstatic --noinput
|
||||
python -m pretix updateassets
|
||||
|
||||
|
||||
.. _Django's documentation: https://docs.djangoproject.com/en/1.11/ref/django-admin/#runserver
|
||||
.. _pretixdroid: https://github.com/pretix/pretixdroid
|
||||
|
||||
@@ -31,7 +31,7 @@ pretix/
|
||||
Additional code implementing our customized :ref:`URL handling <urlconf>`.
|
||||
|
||||
static/
|
||||
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core.
|
||||
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core
|
||||
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
|
||||
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
|
||||
|
||||
@@ -41,6 +41,6 @@ pretix/
|
||||
|
||||
tests/
|
||||
This is the root directory for all test codes. It includes subdirectories ``api``, ``base``,
|
||||
``control``, ``presale``, ``helpers``, ``multidomain`` and ``plugins`` to mirror the structure
|
||||
``control``, ``presale``, ``helpers`, ``multidomain`` and ``plugins`` to mirror the structure
|
||||
of the pretix source code as well as ``testdummy``, which is a pretix plugin used during
|
||||
testing.
|
||||
|
||||
|
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 278 KiB |
@@ -25,27 +25,27 @@ partition "data-based check" {
|
||||
else
|
||||
-down->[yes] "Is one or more block set on the ticket?"
|
||||
--> if "" then
|
||||
-right->[yes] "Return error BLOCKED"
|
||||
-right->[no] "Return error BLOCKED"
|
||||
else
|
||||
-down->[no] "Is the order in status PENDING and not yet approved?"
|
||||
-down->[yes] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
--> if "" then
|
||||
-right->[yes] "Return error UNAPPROVED"
|
||||
-right->[no] "Return error INVALID_TIME"
|
||||
else
|
||||
-down->[no] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
-down->[yes] "Is the product part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error INVALID_TIME"
|
||||
-right->[no] "Return error PRODUCT"
|
||||
else
|
||||
-down->[yes] "Is the product part of the check-in list?"
|
||||
-down->[yes] "Is the subevent part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error PRODUCT"
|
||||
-right->[no] "Return error INVALID"
|
||||
note bottom: TODO\ninconsistent\nwith online\ncheck
|
||||
else
|
||||
-down->[yes] "Is the subevent part of the check-in list?"
|
||||
-down->[yes] "Is the order in status PAID?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error INVALID"
|
||||
note bottom: TODO\ninconsistent\nwith online\ncheck
|
||||
else
|
||||
-down->[yes] "Is the order in status PAID?"
|
||||
-right->[no] "Is Order.require_approval set?"
|
||||
--> if "" then
|
||||
-->[yes] "Return error UNPAID "
|
||||
else
|
||||
-right->[no] "Is Order.valid_if_pending set?"
|
||||
--> if "" then
|
||||
-->[yes] "Is this an entry or exit?"
|
||||
@@ -62,9 +62,9 @@ partition "data-based check" {
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
-down->[yes] "Is this an entry or exit?"
|
||||
endif
|
||||
else
|
||||
-down->[yes] "Is this an entry or exit?"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 180 KiB |
@@ -42,25 +42,23 @@ endif
|
||||
else
|
||||
-down->[yes || force] "Is one or more block set on the ticket?"
|
||||
--> if "" then
|
||||
-right->[yes && !force] "Return error BLOCKED"
|
||||
-right->[no && !force] "Return error BLOCKED"
|
||||
else
|
||||
-down->[no || force] "Is the order in status PENDING and not yet approved?"
|
||||
-down->[yes || force] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
--> if "" then
|
||||
-right->[yes && !force] "Return error UNAPPROVED"
|
||||
-right->[no && !force] "Return error INVALID_TIME"
|
||||
else
|
||||
-down->[no || force] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
-down->[yes || force] "Is the product part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no && !force] "Return error INVALID_TIME"
|
||||
-right->[no && !force] "Return error PRODUCT"
|
||||
else
|
||||
-down->[yes || force] "Is the product part of the check-in list?"
|
||||
-down->[yes || force] "Is the subevent part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no && !force] "Return error PRODUCT"
|
||||
-right->[no && !force] "Return error PRODUCT "
|
||||
else
|
||||
-down->[yes || force] "Is the subevent part of the check-in list?"
|
||||
-down->[yes] "Is the order in status PAID?"
|
||||
--> if "" then
|
||||
-right->[no && !force] "Return error PRODUCT "
|
||||
else
|
||||
-down->[yes] "Is the order in status PAID?"
|
||||
-right->[no && !force] "Is Order.require_approval set?"
|
||||
--> if "" then
|
||||
-->[no] "Is Order.valid_if_pending set?"
|
||||
--> if "" then
|
||||
@@ -79,8 +77,10 @@ else
|
||||
endif
|
||||
endif
|
||||
else
|
||||
-down->[yes || force] "Is this an entry or exit?\nIs the upload forced?"
|
||||
-->[yes] "Return error UNPAID "
|
||||
endif
|
||||
else
|
||||
-down->[yes || force] "Is this an entry or exit?\nIs the upload forced?"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1,29 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 69">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#f8f8f8;}</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="m45.94,31.18l1.72,12.27,4.59-.65-1.44-10.24c.57-.3,1.39-.41,2.3-.11l.34-3.28c-.46.03-.91.07-1.34.13-2.97.39-4.94,1.03-6.17,1.88Z"/>
|
||||
<path class="cls-1"
|
||||
d="m85.33,20.99l-4.43,1.79.37,2.66-1.36.19.42,2.99,1.36-.19.87,6.22c.31,2.24,1.89,3.83,4.83,3.42,1.06-.15,1.84-.54,2.14-.76l-.39-2.81c-.35.17-.52.26-.85.3-.69.1-1.08-.22-1.21-1.19l-.82-5.83,1.87-.26h.03s-.42-3-.42-3l-1.87.26-.54-3.81Z"/>
|
||||
<rect class="cls-1" x="90.72" y="23.89" width="4.64" height="13.12" transform="translate(-3.33 13.25) rotate(-8)"/>
|
||||
<path class="cls-1"
|
||||
d="m91.3,18.09c-1.3.18-2.23,1.24-2.07,2.39s1.35,1.94,2.65,1.75,2.26-1.27,2.09-2.42-1.35-1.91-2.68-1.72Z"/>
|
||||
<polygon class="cls-1"
|
||||
points="108.53 21.65 104.27 22.25 103.01 25.75 102.95 25.76 100.92 22.72 96.15 23.39 100.69 29.16 97.55 36.44 102.17 35.79 103.39 31.95 103.45 31.94 105.62 35.31 105.62 35.34 110.73 34.62 105.6 28.19 108.53 21.65"/>
|
||||
<path class="cls-1"
|
||||
d="m36.92,31.44c-2.51.35-4.11,1.01-5.27,1.76l2.45,17.46,4.59-.65-.73-5.23c.35.04,1.05.04,1.87-.08,3.35-.47,5.38-3.41,4.8-7.51-.64-4.56-3.69-6.32-7.71-5.76Zm1.42,10.77c-.3.04-.55.02-.74-.02l-1.1-7.83c.2-.09.44-.18.77-.23,1.66-.23,2.45,1.01,2.84,3.73s-.13,4.12-1.76,4.35Z"/>
|
||||
<path class="cls-1"
|
||||
d="m60.61,28.14c-4.08.57-5.77,3.68-5.22,7.57s3.19,6.45,7.45,5.86c2.42-.34,3.86-1.01,4.94-1.71l-1.42-2.67c-.67.46-1.84.97-3.38,1.18-1.66.23-2.48-.36-2.98-1.71l7.44-2.12c-.38-4.45-2.71-7.01-6.82-6.41Zm-1.29,6.4c-.44-2.25.11-3.59,1.47-3.78,1.18-.17,1.89.72,2.14,2.72l-3.61,1.06Z"/>
|
||||
<path class="cls-1"
|
||||
d="m122.48,16.27c.33-.08.54-.35.49-.68l-2.1-14.94c-.05-.33-.36-.57-.69-.52L.53,16.94c-.33.05-.57.36-.52.69l2.1,14.94c.05.33.32.54.66.52,5.21-.42,9.92,3.29,10.66,8.55s-2.77,10.1-7.9,11.09c-.33.08-.54.35-.49.68l2.1,14.94c.05.33.36.57.69.52l119.65-16.82c.33-.05.57-.36.52-.69l-2.1-14.94c-.05-.33-.32-.54-.66-.52-5.21.42-9.92-3.26-10.66-8.52s2.77-10.13,7.9-11.12Zm-9.71,11.38c.81,5.77,5.72,10.04,11.47,10.13l1.78,12.64-47.53,6.68-.33-2.34c-.07-.48-.52-.82-1-.75s-.82.5-.75,1l.33,2.34-67.95,9.55-1.78-12.64c5.5-1.64,9.05-7.06,8.24-12.87s-5.73-10.07-11.47-10.16l-1.78-12.64,67.95-9.55.33,2.34c.07.48.52.82,1,.75s.82-.52.75-1l-.33-2.34,47.53-6.68,1.78,12.64c-5.5,1.64-9.05,7.09-8.23,12.9Z"/>
|
||||
<path class="cls-1"
|
||||
d="m75.82,44.49c-.48.07-.82.52-.75,1l.59,4.23c.07.48.52.82,1,.75s.82-.52.75-1l-.59-4.23c-.07-.47-.53-.82-1-.75Z"/>
|
||||
<path class="cls-1"
|
||||
d="m74.46,34.86c-.5.07-.82.5-.75,1l.59,4.23c.07.47.53.82,1,.75s.82-.53.75-1l-.59-4.23c-.07-.48-.52-.82-1-.75Z"/>
|
||||
<path class="cls-1"
|
||||
d="m73.11,25.23c-.48.07-.82.52-.75,1l.59,4.23c.07.48.52.82,1,.75s.82-.52.75-1l-.59-4.23c-.07-.47-.53-.82-1-.75Z"/>
|
||||
<path class="cls-1"
|
||||
d="m71.76,15.6c-.5.07-.82.5-.75,1l.59,4.23c.07.47.53.82,1,.75s.82-.53.75-1l-.59-4.23c-.07-.48-.52-.82-1-.75Z"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="254.156" height="109.594" version="1.1"><g transform="scale(1.9856)"><path d="M36.29 23.21c-.35 0-.61.06-.83.13v8.29c.19.06.45.13.77.13 1.73 0 2.46-1.44 2.46-4.26s-.64-4.29-2.4-4.29z" fill="#f8f8f8"/><path d="M61.22 23.15c-1.44 0-2.21 1.31-2.08 3.71l3.9-.58c.03-2.11-.58-3.14-1.82-3.14z" fill="#f8f8f8"/><path d="M127.39 17.1c.35-.03.61-.29.61-.64V.64c0-.35-.29-.64-.64-.64H75.94v2.48c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12V0H.64C.29 0 0 .29 0 .64v15.82c0 .35.26.61.61.64 5.47.32 9.82 4.86 9.82 10.43 0 5.57-4.35 10.08-9.82 10.37-.35.03-.61.29-.61.64v15.82c0 .35.29.64.64.64h73.22-.16v-2.48c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12V55h-.16 51.58c.35 0 .64-.29.64-.64V38.54c0-.35-.26-.61-.61-.64-5.47-.32-9.82-4.83-9.82-10.4s4.35-10.11 9.82-10.4zM37.41 34.57c-.86 0-1.6-.1-1.95-.19v5.54H30.6v-18.5c1.31-.61 3.07-1.06 5.73-1.06 4.26 0 7.17 2.27 7.17 7.1 0 4.35-2.53 7.1-6.08 7.1zm15.58-10.78c-.9-.45-1.76-.45-2.4-.22v10.85h-4.86V21.43c1.41-.7 3.55-1.09 6.69-1.06.45 0 .93.03 1.41.06L53 23.79Zm14.56 4.26-8.03 1.12c.32 1.47 1.09 2.21 2.85 2.21 1.63 0 2.91-.35 3.68-.74l1.09 2.98c-1.22.58-2.82 1.06-5.38 1.06-4.51 0-6.88-3.04-6.88-7.17s2.21-7.1 6.53-7.1c4.35-.03 6.4 2.98 6.14 7.65zm8.38 18.56c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12v-5.12c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zm0-11.01c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12V8.34c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zM90.11 23.8h-2.02v6.18c0 1.02.35 1.41 1.09 1.41.35 0 .54-.06.93-.19v2.98c-.35.19-1.22.48-2.34.48-3.1 0-4.51-1.89-4.51-4.26v-6.59h-1.44v-3.17h1.44v-2.82l4.86-1.22v4.03h1.98v3.17zm7.07 10.62h-4.86V20.66h4.86zm-2.43-15.58c-1.38 0-2.5-.99-2.5-2.21s1.12-2.18 2.5-2.18 2.53.96 2.53 2.18c0 1.22-1.12 2.21-2.53 2.21zm12.35 15.58-1.76-3.81h-.06l-1.82 3.81h-4.9l4.32-7.1-3.87-6.66h5.06l1.66 3.46h.06l1.82-3.46h4.51l-4 6.37 4.38 7.42-5.41-.03z" fill="#f8f8f8"/></g></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -1,7 +1,7 @@
|
||||
Badges
|
||||
======
|
||||
|
||||
The built-in badges plugin provides a HTTP API that exposes the various layouts used to generate PDF badges.
|
||||
The badges plugin provides a HTTP API that exposes the various layouts used to generate PDF badges.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
@@ -1,7 +1,7 @@
|
||||
Bank transfer
|
||||
=============
|
||||
Bank transfer HTTP API
|
||||
======================
|
||||
|
||||
The built-in banktransfer plugin provides a HTTP API that `pretix-banktool`_ uses to send bank
|
||||
The banktransfer plugin provides a HTTP API that `pretix-banktool`_ uses to send bank
|
||||
transactions to the pretix server. This API is integrated with the regular :ref:`rest-api`
|
||||
and therefore follows the conventions listed there.
|
||||
|
||||
@@ -32,7 +32,6 @@ transactions list of objects Transactions in
|
||||
├ checksum string Checksum computed from payer, reference, amount and
|
||||
date
|
||||
├ payer string Payment source
|
||||
├ external_id string Unique ID of the payment from an external source
|
||||
├ reference string Payment reference
|
||||
├ amount string Payment amount
|
||||
├ iban string Payment IBAN
|
||||
@@ -86,7 +85,6 @@ Endpoints
|
||||
"date": "26.06.2017",
|
||||
"payer": "John Doe",
|
||||
"order": null,
|
||||
"external_id": null,
|
||||
"iban": "",
|
||||
"bic": "",
|
||||
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
|
||||
@@ -141,7 +139,6 @@ Endpoints
|
||||
"iban": "",
|
||||
"bic": "",
|
||||
"order": null,
|
||||
"external_id": null,
|
||||
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
|
||||
"reference": "GUTSCHRIFT\r\nSAMPLECONF-NAB12 EREF: SAMPLECONF-NAB12\r\nIBAN: DE1234556…",
|
||||
"state": "nomatch",
|
||||
@@ -1,8 +1,6 @@
|
||||
Campaigns
|
||||
=========
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-campaigns** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
The campaigns plugin provides a HTTP API that allows you to create new campaigns.
|
||||
|
||||
Resource description
|
||||
@@ -1,8 +1,6 @@
|
||||
Certificates of attendance
|
||||
==========================
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-certificates** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
The certificates plugin provides a HTTP API that allows you to download the certificate for a specific attendee.
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Digital content
|
||||
===============
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-digital** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
URL interpolation and JWT authentication
|
||||
----------------------------------------
|
||||
|
||||
143
doc/plugins/epaybl.rst
Normal file
@@ -0,0 +1,143 @@
|
||||
ePayBL
|
||||
======
|
||||
|
||||
.. note::
|
||||
|
||||
Since ePayBL is only available to german federal, provincial and communal entities, the following page is also
|
||||
only provided in german. Should you require assistance with ePayBL and do not speak this language, please feel free
|
||||
reach out to support@pretix.eu.
|
||||
|
||||
|
||||
Einführung
|
||||
----------
|
||||
|
||||
.. note::
|
||||
|
||||
Sollten Sie lediglich schnell entscheiden wollen, welcher Kontierungsmodus in den Einstellungen des pretix
|
||||
ePayBL-plugins gewählt werden soll, so springen Sie direkt zur Sektion :ref:`Kontierungsmodus`.
|
||||
|
||||
|
||||
`ePayBL`_ - das ePayment-System von Bund und Länder - ist das am weitesten verbreitete Zahlungssystem für Bundes-, Länder-
|
||||
sowie kommunale Aufgabenträger. Während es nur wie eines von vielen anderen Zahlungssystemen scheint, so bietet es
|
||||
seinen Nutzern besondere Vorteile, wie die automatische Erfassung von Zahlungsbelegen, dem Übertragen von Buchungen in
|
||||
Haushaltskassen/-systeme sowie die automatische Erfassung von Kontierungen und Steuermerkmalen.
|
||||
|
||||
Rein technisch gesehen ist ePayBL hierbei nicht ein eigenständiger Zahlungsdienstleister sondern nur ein eine Komponente
|
||||
im komplexen System, dass die Zahlungsabwicklung für Kommunen und Behörden ist.
|
||||
|
||||
Im folgenden der schematische Aufbau einer Umgebung, in welcher ePayBL zum Einsatz kommt:
|
||||
|
||||
.. figure:: img/epaybl_flowchart.png
|
||||
:class: screenshot
|
||||
|
||||
Quelle: Integrationshandbuch ePayBL-Konnektor, DResearch Digital Media Systems GmbH
|
||||
|
||||
|
||||
In diesem Schaubild stellt pretix, bzw. die von Ihnen als Veranstalter angelegten Ticketshops, das Fachverfahren dar.
|
||||
|
||||
ePayBL stellt das Bindeglied zwischen den Fachverfahren, Haushaltssystemen und dem eigentlichen Zahlungsdienstleister,
|
||||
dem sog. ZV-Provider dar. Dieser ZV-Provider ist die Stelle, welche die eigentlichen Kundengelder einzieht und an den
|
||||
Händler auszahlt. Das Gros der Zahlungsdienstleister unterstützt pretix hierbei auch direkt; sprich: Sollten Sie die
|
||||
Anbindung an Ihre Haushaltssysteme nicht benötigen, kann eine direkte Anbindung in der Regel ebenso - und dies bei meist
|
||||
vermindertem Aufwand - vorgenommen werden.
|
||||
|
||||
In der Vergangenheit zeigte sich jedoch schnell, dass nicht jeder IT-Dienstleister immer sofort die neueste Version von
|
||||
ePayBL seinen Nutzern angeboten hat. Die Gründe hierfür sind mannigfaltig: Von fest vorgegebenen Update-Zyklen bis hin
|
||||
zu Systeme mit speziellen Anpassungen, kann leider nicht davon ausgegangen werden, dass alle ePayBL-Systeme exakt gleich
|
||||
ansprechbar sind - auch wenn es sich dabei eigentlich um einen standardisierten Dienst handelt.
|
||||
|
||||
Aus diesem Grund gibt es mit dem ePayBL-Konnektor eine weitere Abstraktionsschicht welche optional zwischen den
|
||||
Fachverfahren und dem ePayBL-Server sitzt. Dieser Konnektor wird so gepflegt, dass er zum einen eine dauerhaft
|
||||
gleichartige Schnittstelle den Fachverfahren bietet aber gleichzeitig auch mit jeder Version des ePayBL-Servers
|
||||
kommunizieren kann - egal wie neu oder alt, wie regulär oder angepasst diese ist.
|
||||
|
||||
Im Grunde müsste daher eigentlich immer gesagt werden, dass pretix eine Anbindung an den ePayBL-Konnektor bietet; nicht
|
||||
an "ePayBL" oder den "ePayBL-Server". Diese Unterscheidung kann bei der Ersteinrichtung und Anforderung von Zugangsdaten
|
||||
von Relevanz sein. Da in der Praxis jedoch beide Begriffe gleichbedeutend genutzt werden, wird im Folgenden auch nur von
|
||||
einer ePayBL-Anbindung die Rede sein - auch wenn explizit der Konnektor gemeint ist.
|
||||
|
||||
|
||||
.. _`Kontierungsmodus`:
|
||||
|
||||
Kontierungsmodus
|
||||
----------------
|
||||
|
||||
ePayBL ist ein Produkt, welches für die Abwicklung von Online-Zahlungsvorgängen in der Verwaltung geschaffen wurde. Ein
|
||||
Umfeld, in dem klar definiert ist, was ein Kunde gerade bezahlt und wohin das Geld genau fließt. Diese Annahmen lassen
|
||||
sich in einem Ticketshop wie pretix jedoch nur teilweise genauso abbilden.
|
||||
|
||||
Die ePayBL-Integration für pretix bietet daher zwei unterschiedliche Modi an, wie Buchungen erfasst und an ePayBL und
|
||||
damit auch an die dahinterliegenden Haushaltssysteme gemeldet werden können.
|
||||
|
||||
Kontierung pro Position/Artikel
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Dieser Modus versucht den klassischen, behördentypischen ePayBL-Zahlungsvorgang abzubilden: Jede einzelne Position, die
|
||||
ein Kunde in den Warenkorb legt, wird auch genauso 1:1 an ePayBL und die Hintergrundsysteme übermittelt.
|
||||
|
||||
Hierbei muss zwingend auch für jede Position ein Kennzeichen für Haushaltsstelle und Objektnummer, sowie optional ein
|
||||
Kontierungsobjekt (``HREF``; bspw. ``stsl=Steuerschlüssel;psp=gsb:Geschäftsbereich,auft:Innenauftrag,kst:Kostenstelle;``
|
||||
) übermittelt werden.
|
||||
|
||||
Diese Daten sind vom Veranstalter entsprechend für jeden in der Veranstaltung angelegten Artikel innerhalb des Tabs
|
||||
"Zusätzliche Einstellungen" der Produkteinstellungen zu hinterlegen.
|
||||
|
||||
Während diese Einstellung eine größtmögliche Menge an Kontierungsdaten überträgt und auch ein separates Verbuchen von
|
||||
Leistungen auf unterschiedliche Haushaltsstellen erlaubt, so hat diese Option auch einen großen Nachteil: Der Kunde kann
|
||||
nur eine Zahlung für seine Bestellung leisten.
|
||||
|
||||
Während sich dies nicht nach einem großen Problem anhört, so kann dies beim Kunden zu Frust führen. pretix bietet die
|
||||
Option an, dass ein Veranstalter eine Bestellung jederzeit verändern kann: Ändern von Preisen von Positionen in einer
|
||||
aufgegebenen Bestellung, Zubuchen und Entfernen von Bestellpositionen, etc. Hat der Kunde seine ursprüngliche Bestellung
|
||||
jedoch schon bezahlt, kann pretix nicht mehr die komplette Bestellung mit den passenden Kontierungen übertragen - es
|
||||
müsste nur ein Differenz-Abbild zwischen Ursprungsbestellung und aktueller Bestellung übertragen werden. Aber auch wenn
|
||||
eine "Nachmeldung" möglich wäre, so wäre ein konkretes Auflösen für was jetzt genau gezahlt wird, nicht mehr möglich.
|
||||
|
||||
Daher gilt bei der Nutzung der Kontierung pro Position/Artikel: Der Kunde kann nur eine (erfolgreiche) Zahlung auf seine
|
||||
Bestellung leisten.
|
||||
|
||||
Eine weitere Einschränkung dieses Modus ist, dass aktuell keine Gebühren-Positionen (Versandkosten, Zahlungs-, Storno-
|
||||
oder Servicegebühren) in diesem Modus übertragen werden können. Bitte wenden Sie sich an uns, wenn Sie diese
|
||||
Funktionalität benötigen.
|
||||
|
||||
|
||||
Kontierung pro Zahlvorgang
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Dieser Modus verabschiedet sich vom behördlichen "Jede Position gehört genau zu einem Haushaltskonto und muss genau
|
||||
zugeordnet werden". Stattdessen werden alle Bestellpositionen - inklusive eventuell definierter Gebühren - vermengt und
|
||||
nur als ein großer Warenkorb, genauer gesagt: eine einzige Position an ePayBL sowie die Hintergrundsysteme gemeldet.
|
||||
|
||||
Während im "pro Postion/Artikel"-Modus jeder Artikel einzeln übermittelt wird und damit auch korrekt pro Artikel der
|
||||
jeweilige Brutto- und Nettopreis, sowie der anfallende Steuerbetrag und ein Steuerkennzeichen (mit Hilfe des optionalen
|
||||
``HREF``-Attributs) übermittelt werden, ist dies im "pro Zahlvorgang"-Modus nicht möglich.
|
||||
|
||||
Stattdessen übermittelt pretix nur einen Betrag für den gesamten Warenkorb: Bruttopreis == Nettopreis. Der Steuerbetrag
|
||||
wird hierbei als 0 übermittelt.
|
||||
|
||||
Die Angabe einer Haushaltsstelle und Objektnummer, sowie optional der ``HREF``-Kontierungsinformationen ist jedoch
|
||||
weiterhin notwendig - allerdings nicht mehr individuell für jeden Artikel/jede Position sondern nur für die gesamte
|
||||
Bestellung. Diese Daten sind direkt in den ePayBL-Einstellungen der Veranstaltung unter Einstellungen -> Zahlung ->
|
||||
ePayBL vorzunehmen
|
||||
|
||||
In der Praxis bedeutet dies, dass in einem angeschlossenen Haushaltssystem nicht nachvollzogen kann, welche Positionen
|
||||
konkret erworben und bezahlt wurden - stattdessen kann nur der Fakt, dass etwas verkauft wurde erfasst werden.
|
||||
|
||||
Je nach Aufbau und Vorgaben der Finanzbuchhaltung kann dies jedoch ausreichend sein - wenn bspw. eine Ferienfahrt
|
||||
angeboten wird und seitens der Haushaltssysteme nicht erfasst werden muss, wie viel vom Gesamtbetrag einer Bestellung
|
||||
auf die Ferienfahrt an sich, auf einen Zubringerbus und einen Satz Bettwäsche entfallen ist, sondern (vereinfacht
|
||||
gesagt) es ausreichend ist, dass "Eine Summe X für die Haushaltsstelle/Objektnummer geflossen ist".
|
||||
|
||||
Dieser Modus der Kontierung bietet Ihnen auch als Vorteil gegenüber dem vorhergehenden an, dass die Bestellungen der
|
||||
Kunden jederzeit erweitert und verändert werden können - auch wenn die Ursprungsbestellung schon bezahlt wurde und nur
|
||||
noch eine Differenz gezahlt wird.
|
||||
|
||||
|
||||
Einschränkungen
|
||||
---------------
|
||||
|
||||
Zum aktuellen Zeitpunkt erlaubt die pretix-Anbindung an ePayBL nicht das durchführen von Erstattungen von bereits
|
||||
geleisteten Zahlungen. Der Prozess hierfür unterscheidet sich von Behörde zu Behörde und muss daher händisch
|
||||
durchgeführt werden.
|
||||
|
||||
.. _ePayBL: https://www.epaybl.de/
|
||||
@@ -1,8 +1,6 @@
|
||||
Exhibitors
|
||||
==========
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-exhibitors** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
The exhibitors plugin allows to manage exhibitors at your trade show or conference. After signing up your exhibitors
|
||||
in the system, you can assign vouchers to exhibitors and give them access to the data of these vouchers. The exhibitors
|
||||
module is also the basis of the pretixLEAD lead scanning application.
|
||||
@@ -36,19 +34,13 @@ internal_id string Can be used for
|
||||
contact_name string Contact person (or ``null``)
|
||||
contact_name_parts object of strings Decomposition of contact name (i.e. given name, family name)
|
||||
contact_email string Contact person email address (or ``null``)
|
||||
contact_cc_email string Copy email addresses, can be multiple separated by comma (or ``null``)
|
||||
booth string Booth number (or ``null``). Maximum 100 characters.
|
||||
locale string Locale for communication with the exhibitor.
|
||||
locale string Locale for communication with the exhibitor (or ``null``).
|
||||
access_code string Access code for the exhibitor to access their data or use the lead scanning app (read-only).
|
||||
lead_scanning_access_code string Access code for the exhibitor to use the lead scanning app but not access data (read-only).
|
||||
allow_lead_scanning boolean Enables lead scanning app
|
||||
allow_lead_access boolean Enables access to data gathered by the lead scanning app
|
||||
allow_voucher_access boolean Enables access to data gathered by exhibitor vouchers
|
||||
lead_scanning_scope_by_device string Enables lead scanning to be handled as one lead per attendee
|
||||
per scanning device, instead of only per exhibitor.
|
||||
comment string Internal comment, not shown to exhibitor
|
||||
exhibitor_tags list of strings Internal tags to categorize exhibitors, not shown to exhibitor.
|
||||
The tags need to be created through the web interface currently.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
You can also access the scanned leads through the API which contains the following public fields:
|
||||
@@ -70,7 +62,6 @@ data list of objects Attendee data s
|
||||
except in a few cases where it contains an additional list of objects
|
||||
with ``value`` and ``label`` keys (e.g. splitting of names).
|
||||
device_name string User-defined name for the device used for scanning (or ``null``).
|
||||
device_uuid string UUID of device used for scanning (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
@@ -114,17 +105,13 @@ Endpoints
|
||||
"title": "Dr"
|
||||
},
|
||||
"contact_email": "johnson@as.example.org",
|
||||
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
|
||||
"booth": "A2",
|
||||
"locale": "de",
|
||||
"access_code": "VKHZ2FU84",
|
||||
"lead_scanning_access_code": "WVK2B8PZ",
|
||||
"lead_scanning_scope_by_device": false,
|
||||
"access_code": "VKHZ2FU8",
|
||||
"allow_lead_scanning": true,
|
||||
"allow_lead_access": true,
|
||||
"allow_voucher_access": true,
|
||||
"comment": "",
|
||||
"exhibitor_tags": []
|
||||
"comment": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -169,17 +156,13 @@ Endpoints
|
||||
"title": "Dr"
|
||||
},
|
||||
"contact_email": "johnson@as.example.org",
|
||||
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
|
||||
"booth": "A2",
|
||||
"locale": "de",
|
||||
"access_code": "VKHZ2FU84",
|
||||
"lead_scanning_access_code": "WVK2B8PZ",
|
||||
"lead_scanning_scope_by_device": false,
|
||||
"access_code": "VKHZ2FU8",
|
||||
"allow_lead_scanning": true,
|
||||
"allow_lead_access": true,
|
||||
"allow_voucher_access": true,
|
||||
"comment": "",
|
||||
"exhibitor_tags": []
|
||||
"comment": ""
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -247,8 +230,7 @@ Endpoints
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/
|
||||
|
||||
Returns a list of all vouchers connected to an exhibitor. The response contains the same data as described in
|
||||
:ref:`rest-vouchers` as well as for each voucher an additional field ``exhibitor_comment`` that is shown to the exhibitor. It can only
|
||||
be modified using the ``attach`` API call below.
|
||||
:ref:`rest-vouchers`.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -303,7 +285,7 @@ Endpoints
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/attach/
|
||||
|
||||
Attaches an **existing** voucher to an exhibitor. You need to send either the ``id`` **or** the ``code`` field of
|
||||
the voucher. You can call this method multiple times to update the optional ``exhibitor_comment`` field.
|
||||
the voucher.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -314,8 +296,7 @@ Endpoints
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
{
|
||||
"id": 15,
|
||||
"exhibitor_comment": "Free ticket"
|
||||
"id": 15
|
||||
}
|
||||
|
||||
**Example request**:
|
||||
@@ -327,8 +308,7 @@ Endpoints
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
{
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"exhibitor_comment": "Free ticket"
|
||||
"code": "43K6LKM37FBVR2YG"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -374,16 +354,13 @@ Endpoints
|
||||
"title": "Dr"
|
||||
},
|
||||
"contact_email": "johnson@as.example.org",
|
||||
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
|
||||
"booth": "A2",
|
||||
"locale": "de",
|
||||
"access_code": "VKHZ2FU8",
|
||||
"allow_lead_scanning": true,
|
||||
"allow_lead_access": true,
|
||||
"allow_voucher_access": true,
|
||||
"comment": "",
|
||||
"exhibitor_tags": [
|
||||
"Gold Sponsor"
|
||||
]
|
||||
"comment": ""
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -407,19 +384,13 @@ Endpoints
|
||||
"title": "Dr"
|
||||
},
|
||||
"contact_email": "johnson@as.example.org",
|
||||
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
|
||||
"booth": "A2",
|
||||
"locale": "de",
|
||||
"access_code": "VKHZ2FU84",
|
||||
"lead_scanning_access_code": "WVK2B8PZ",
|
||||
"lead_scanning_scope_by_device": false,
|
||||
"access_code": "VKHZ2FU8",
|
||||
"allow_lead_scanning": true,
|
||||
"allow_lead_access": true,
|
||||
"allow_voucher_access": true,
|
||||
"comment": "",
|
||||
"exhibitor_tags": [
|
||||
"Gold Sponsor"
|
||||
]
|
||||
"comment": ""
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create new exhibitor for
|
||||
@@ -440,7 +411,7 @@ Endpoints
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/ HTTP/1.1
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/digitalcontents/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
@@ -471,19 +442,13 @@ Endpoints
|
||||
"title": "Dr"
|
||||
},
|
||||
"contact_email": "johnson@as.example.org",
|
||||
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
|
||||
"booth": "A2",
|
||||
"locale": "de",
|
||||
"access_code": "VKHZ2FU84",
|
||||
"lead_scanning_access_code": "WVK2B8PZ",
|
||||
"lead_scanning_scope_by_device": false,
|
||||
"access_code": "VKHZ2FU8",
|
||||
"allow_lead_scanning": true,
|
||||
"allow_lead_access": true,
|
||||
"allow_voucher_access": true,
|
||||
"comment": "",
|
||||
"exhibitor_tags": [
|
||||
"Gold Sponsor"
|
||||
]
|
||||
"comment": ""
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
@@ -494,36 +459,6 @@ Endpoints
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/exhibitor does not exist **or** you have no permission to change it.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/send_access_code/
|
||||
|
||||
Sends an email to the exhibitor with their access code.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/send_access_code/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param code: The ``id`` field of the exhibitor to send an email for
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The exhibitor does not have an email address associated
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested exhibitor does not exist.
|
||||
:statuscode 503: The email could not be sent.
|
||||
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/
|
||||
|
||||
@@ -594,7 +529,6 @@ name string Exhibitor name
|
||||
booth string Booth number (or ``null``)
|
||||
event object Object describing the event
|
||||
├ name multi-lingual string Event name
|
||||
├ end_date datetime End date of the event. After this time, the app could show a warning that the event is over.
|
||||
├ imprint_url string URL to legal notice page. If not ``null``, a button in the app should link to this page.
|
||||
├ privacy_url string URL to privacy notice page. If not ``null``, a button in the app should link to this page.
|
||||
├ help_url string URL to help page. If not ``null``, a button in the app should link to this page.
|
||||
@@ -630,7 +564,6 @@ scan_types list of objects Only used for a
|
||||
"booth": "A2",
|
||||
"event": {
|
||||
"name": {"en": "Sample conference", "de": "Beispielkonferenz"},
|
||||
"end_date": "2017-12-28T10:00:00+00:00",
|
||||
"slug": "bigevents",
|
||||
"imprint_url": null,
|
||||
"privacy_url": null,
|
||||
@@ -669,7 +602,6 @@ On the request, you should set the following properties:
|
||||
* ``tags`` with the list of selected tags
|
||||
* ``rating`` with the rating assigned by the exhibitor
|
||||
* ``device_name`` with a user-specified name of the device used for scanning (max. 190 characters), or ``null``
|
||||
* ``device_uuid`` with a auto-generated UUID of the device used for scanning, or ``null``
|
||||
|
||||
If you submit ``tags`` and ``rating`` to be ``null`` and ``notes`` to be ``""``, the server
|
||||
responds with the previously saved information and will not delete that information. If you
|
||||
@@ -704,8 +636,7 @@ The request for this looks like this:
|
||||
"scan_type": "lead",
|
||||
"tags": ["foo"],
|
||||
"rating": 4,
|
||||
"device_name": "DEV1",
|
||||
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
|
||||
"device_name": "DEV1"
|
||||
}
|
||||
|
||||
**Example response:**
|
||||
@@ -738,9 +669,7 @@ The request for this looks like this:
|
||||
},
|
||||
"rating": 4,
|
||||
"tags": ["foo"],
|
||||
"notes": "Great customer, wants our newsletter",
|
||||
"device_name": "DEV1",
|
||||
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
|
||||
"notes": "Great customer, wants our newsletter"
|
||||
}
|
||||
|
||||
:statuscode 200: No error, leads was not scanned for the first time
|
||||
@@ -795,9 +724,7 @@ You can also fetch existing leads (if you are authorized to do so):
|
||||
},
|
||||
"rating": 4,
|
||||
"tags": ["foo"],
|
||||
"notes": "Great customer, wants our newsletter",
|
||||
"device_name": "DEV1",
|
||||
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
|
||||
"notes": "Great customer, wants our newsletter"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
doc/plugins/img/epaybl_flowchart.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
@@ -1,8 +1,6 @@
|
||||
Secrets Import
|
||||
==============
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-secrets-import** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
Usually, pretix generates ticket secrets (i.e. the QR code used for scanning) itself. You can read more about this
|
||||
process at :ref:`secret_generators`.
|
||||
|
||||
26
doc/plugins/index.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
.. _`plugin-docs`:
|
||||
|
||||
Plugin documentation
|
||||
====================
|
||||
|
||||
This part of the documentation contains information about available plugins
|
||||
that can be used to extend pretix's functionality.
|
||||
If you want to **create** a plugin, please go to the
|
||||
:ref:`Developer documentation <pluginsetup>` instead.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
list
|
||||
banktransfer
|
||||
ticketoutputpdf
|
||||
badges
|
||||
campaigns
|
||||
certificates
|
||||
digital
|
||||
epaybl
|
||||
exhibitors
|
||||
shipping
|
||||
imported_secrets
|
||||
webinar
|
||||
presale-saml
|
||||
10
doc/plugins/list.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
.. spelling:word-list::
|
||||
Analytics
|
||||
|
||||
List of plugins
|
||||
===============
|
||||
|
||||
A detailed list of plugins that are available for pretix can be found on the
|
||||
`pretix Marketplace`_.
|
||||
|
||||
.. _pretix Marketplace: https://marketplace.pretix.eu
|
||||
405
doc/plugins/presale-saml.rst
Normal file
@@ -0,0 +1,405 @@
|
||||
.. highlight:: ini
|
||||
.. spelling:word-list::
|
||||
|
||||
IdP
|
||||
skIDentity
|
||||
ePA
|
||||
NPA
|
||||
|
||||
Presale SAML Authentication
|
||||
===========================
|
||||
|
||||
The Presale SAML Authentication plugin is an advanced plugin, which most event
|
||||
organizers will not need to use. However, for the select few who do require
|
||||
strong customer authentication that cannot be covered by the built-in customer
|
||||
account functionality, this plugin allows pretix to connect to a SAML IdP and
|
||||
perform authentication and retrieval of user information.
|
||||
|
||||
Usage of the plugin is governed by two separate sets of settings: The plugin
|
||||
installation, the Service Provider (SP) configuration and the event
|
||||
configuration.
|
||||
|
||||
Plugin installation and initial configuration
|
||||
---------------------------------------------
|
||||
|
||||
.. note:: If you are a customer of our hosted `pretix.eu`_ offering, you can
|
||||
skip this section.
|
||||
|
||||
The plugin is installed as any other plugin in the pretix ecosystem. As a
|
||||
pretix system administrator, please follow the instructions in the the
|
||||
:ref:`Administrator documentation <admindocs>`.
|
||||
|
||||
Once installed, you will need to assess, if you want (or need) your pretix
|
||||
instance to be a single SP for all organizers and events or if every event
|
||||
organizer has to provide their own SP.
|
||||
|
||||
Take the example of a university which runs pretix under an pretix Enterprise
|
||||
agreement. Since they only provide ticketing services to themselves (every
|
||||
organizer is still just a different department of the same university), a
|
||||
single SP should be enough.
|
||||
|
||||
On the other hand, a reseller such as `pretix.eu`_ who services a multitude
|
||||
of clients would not work that way. Here, every organizer is a separate
|
||||
legal entity and as such will also need to provide their own SP configuration:
|
||||
Company A will expect their SP to reflect their company - and not a generalized
|
||||
"pretix SP".
|
||||
|
||||
Once you have decided on the mode of operation, the :ref:`Configuration file
|
||||
<config>` needs to be extended to reflect your choice.
|
||||
|
||||
Example::
|
||||
|
||||
[presale-saml]
|
||||
level=global
|
||||
|
||||
``level``
|
||||
``global`` to use only a single, system-wide SP, ``organizer`` for multiple
|
||||
SPs, configured on the organizer-level. Defaults to ``organizer``.
|
||||
|
||||
Service Provider configuration
|
||||
------------------------------
|
||||
|
||||
Global Level
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. note:: If you are a customer of our hosted `pretix.eu`_ offering, you can
|
||||
skip this section and follow the instructions on the upcoming
|
||||
Organizer Level settings.
|
||||
|
||||
As a user with administrative privileges, please activate them by clicking the
|
||||
`Admin Mode` button in the top right hand corner.
|
||||
|
||||
You should now see a new menu-item titled `SAML` appear.
|
||||
|
||||
Organizer Level
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Navigate to the organizer settings in the pretix backend. In the navigation
|
||||
bar, you will find a menu-item titled `SAML` if your user has the `Can
|
||||
change organizer settings` permission.
|
||||
|
||||
|
||||
.. note:: If you are a customer of our hosted `pretix.eu`_ offering, the menu
|
||||
will only appear once one of our friendly customer service agents
|
||||
has enabled the Presale SAML Authentication plugin for at least one
|
||||
of your events. Feel free to get in touch with us!
|
||||
|
||||
Setting up the SP
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
No matter where your SP configuration lives, you will be greeted by a very
|
||||
long list of fields of which almost all of them will need to be filled. Please
|
||||
don't be discouraged - most of the settings don't need to be decided by yourself
|
||||
and/or are already preset with a sensible default setting.
|
||||
|
||||
If you are not sure what setting you should choose for any of the fields, you
|
||||
should reach out to your IdP operator as they can tell you exactly what the IdP
|
||||
expects and - more importantly - supports.
|
||||
|
||||
``IdP Metadata URL``
|
||||
Please provide the URL where your IdP outputs its metadata. For most IdPs,
|
||||
this URL is static and the same for all SPs. If you are a member of the
|
||||
DFN-AAI, you can find the meta-data for the `Test-, Basic- and
|
||||
Advanced-Federation`_ on their website. Please do talk with your local
|
||||
IdP operator though, as you might not even need to go through the DFN-AAI
|
||||
and might just use your institutions local IdP which will also host their
|
||||
metadata on a different URL.
|
||||
|
||||
The URL needs to be publicly accessible, as saving the settings form will
|
||||
fail if the IdP metadata cannot be retrieved. pretix will also automatically
|
||||
refresh the IdP metadata on a regular basis.
|
||||
|
||||
``SP Entity Id``
|
||||
By default, we recommend that you use the system-proposed metadata-URL as
|
||||
the Entity Id of your SP. However, if so desired or required by your IdP,
|
||||
you can also set any other, arbitrary URL as the SP Entity Id.
|
||||
|
||||
``SP Name / SP Decription``
|
||||
Most IdP will display the name and description of your SP to the users
|
||||
during authentication. The description field can be used to explain to the
|
||||
users how their data is being used.
|
||||
|
||||
``SP X.509 Certificate / SP X.509 Private Key``
|
||||
Your SP needs a certificate and a private key for said certificate. Please
|
||||
coordinate with your IdP, if you are supposed to generate these yourself or
|
||||
if they are provided to you.
|
||||
|
||||
``SP X.509 New Certificate``
|
||||
As certificates have an expiry date, they need to be renewed on a regular
|
||||
basis. In order to facilitate the rollover from the expiring to the new
|
||||
certificate, you can provide the new certificate already before the expiration
|
||||
of the existing one. That way, the system will automatically use the correct
|
||||
one. Once the old certificate has expired and is not used anymore at all,
|
||||
you can move the new certificate into the slot of the normal certificate and
|
||||
keep the new slot empty for your next renewal process.
|
||||
|
||||
``Requested Attributes``
|
||||
An IdP can hold a variety of attributes of an authenticating user. While
|
||||
your IdP will dictate which of the available attributes your SP can consume
|
||||
in theory, you will still need to define exactly which attributes the SP
|
||||
should request.
|
||||
|
||||
The notation is a JSON list of objects with 5 attributes each:
|
||||
|
||||
* ``attributeValue``: Can be defaulted to ``[]``.
|
||||
* ``friendlyName``: String used in the upcoming event-level settings to
|
||||
retrieve the attributes data.
|
||||
* ``isRequired``: Boolean indicating whether the IdP must enforce the
|
||||
transmission of this attribute. In most cases, ``true`` is the best
|
||||
choice.
|
||||
* ``name``: String of the internal, technical name of the requested
|
||||
attribute. Often starting with ``urn:mace:dir:attribute-def:``,
|
||||
``urn:oid:`` or ``http://``/``https://``.
|
||||
* ``nameFormat``: String describing the type of ``name`` that has been
|
||||
set in the previous section. Often starting with
|
||||
``urn:mace:shibboleth:1.0:`` or ``urn:oasis:names:tc:SAML:2.0:``.
|
||||
|
||||
Your IdP can provide you with a list of available attributes. See below
|
||||
for a sample configuration in an academic context.
|
||||
|
||||
Note, that you can have multiple attributes with the same ``friendlyName``
|
||||
but different ``name``s. This is often used in systems, where the same
|
||||
information (for example a persons name) is saved in different fields -
|
||||
for example because one institution is returning SAML 1.0 and other
|
||||
institutions are returning SAML 2.0 style attributes. Typically, this only
|
||||
occurs in mix environments like the DFN-AAI with a large number of
|
||||
participants. If you are only using your own institutions IdP and not
|
||||
authenticating anyone outside of your realm, this should not be a common
|
||||
sight.
|
||||
|
||||
``Encrypt/Sign/Require ...``
|
||||
Does what is says on the box - please inquire with your IdP for the
|
||||
necessary settings. Most settings can be turned on as they increase security,
|
||||
however some IdPs might stumble over some of them.
|
||||
|
||||
``Signature / Digest Algorithm``
|
||||
Please chose appropriate algorithms, that both pretix/your SP and the IdP
|
||||
can communicate with. A common source of issues when connecting to a
|
||||
Shibboleth-based IdP is the Digest Algorithm: pretix does not support
|
||||
``http://www.w3.org/2009/xmlenc11#rsa-oaep`` and authentication will fail
|
||||
if the IdP enforces this.
|
||||
|
||||
``Technical/Support Contacts``
|
||||
Those contacts are encoded into the SPs public meta data and might be
|
||||
displayed to users having trouble authenticating. It is recommended to
|
||||
provide a dedicated point of contact for technical issues, as those will
|
||||
be the ones to change the configuration for the SP.
|
||||
|
||||
Event / Authentication configuration
|
||||
------------------------------------
|
||||
|
||||
Basic settings
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Once the plugin has been enabled for a pretix event using the Plugins-menu from
|
||||
the event's settings, a new *SAML* menu item will show up.
|
||||
|
||||
On this page, the actual authentication can be configured.
|
||||
|
||||
``Checkout Explanation``
|
||||
Since most users probably won't be familiar with why they have to authenticate
|
||||
to buy a ticket, you can provide them a small blurb here. Markdown is supported.
|
||||
|
||||
``Attribute RegEx``
|
||||
By default, any successful authentication with the IdP will allow the user to
|
||||
proceed with their purchase. Should the allowed audience needed to be restricted
|
||||
further, a set of regular Expressions can be used to do this.
|
||||
|
||||
An Attribute RegEx of ``{}`` will allow any authenticated user to pass.
|
||||
|
||||
A RegEx of ``{ "affiliation": "^(employee@pretix.eu|staff@pretix.eu)$" }`` will
|
||||
only allow user to pass which have the ``affiliation`` attribute and whose
|
||||
attribute either matches ``employee@pretix.eu`` or ``staff@pretix.eu``.
|
||||
|
||||
Please make sure that the attribute you are querying is also requested from the
|
||||
IdP in the first place - for a quick check you can have a look at the top of
|
||||
the page where all currently configured attributes are listed.
|
||||
|
||||
``RegEx Fail Explanation``
|
||||
Only used in conjunction with the above Attribute RegEx. Should the user not
|
||||
pass the restrictions imposed by the regular expression, the user is shown
|
||||
this error-message.
|
||||
|
||||
If you are - for example in an university context - restricting access to
|
||||
students only, you might want to explain here that Employees are not allowed
|
||||
to book tickets.
|
||||
|
||||
``Ticket Secret SAML Attribute``
|
||||
In very specific instances, it might be desirable that the ticket-secret is
|
||||
not the randomly one generated by pretix but rather based on one of the
|
||||
users attributes - for example their unique ID or access card number.
|
||||
|
||||
To achieve this, the name of a SAML-attribute can be specified here.
|
||||
|
||||
It is however necessary to note, that even with this setting in use,
|
||||
ticket-secrets need to be unique. This is why when this setting is enabled,
|
||||
the default, pretix-generated ticket-secret is prefixed with the attributes
|
||||
value.
|
||||
|
||||
Example: A users ``cardid`` attribute has the value of ``01189998819991197253``.
|
||||
The default random ticket secret would have been
|
||||
``yczygpw9877akz2xwdhtdyvdqwkv7npj``. The resulting new secret will now be
|
||||
``01189998819991197253_yczygpw9877akz2xwdhtdyvdqwkv7npj``.
|
||||
|
||||
That way, the ticket secret is still unique, but when checking into an event,
|
||||
the user can easily be searched and found using their identifier.
|
||||
|
||||
IdP-provided E-Mail addresses, names
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
By default, pretix will only authenticate the user and not process the received
|
||||
data any further.
|
||||
|
||||
However, there are a few exceptions to this rule.
|
||||
|
||||
There are a few `magic` attributes that pretix will use to automatically populate
|
||||
the corresponding fields within the checkout process **and lock them out from
|
||||
user editing**.
|
||||
|
||||
* ``givenName`` and ``sn``: If both of those attributes are present and pretix
|
||||
is configured to collect the users name, these attributes' values are used
|
||||
for the given and family name respectively.
|
||||
* ``email``: If this attribute is present, the E-Mail-address of the users will
|
||||
be set to the one transmitted through the attributes.
|
||||
|
||||
The latter might pose a problem, if the IdP is transmitting an ``email`` attribute
|
||||
which does contain a system-level mail address which is only used as an internal
|
||||
identifier but not as a real mailbox. In this case, please consider setting the
|
||||
``friendlyName`` of the attribute to a different value than ``email`` or removing
|
||||
this field from the list of requested attributes altogether.
|
||||
|
||||
Saving attributes to questions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
By setting the ``internal identifier`` of a user-defined question to the same name
|
||||
as a SAML attribute, pretix will save the value of said attribute into the question.
|
||||
|
||||
All the same as in the above section on E-Mail addresses, those fields become
|
||||
non-editable by the user.
|
||||
|
||||
Please be aware that some specialty question types might not be compatible with
|
||||
the SAML attributes due to specific format requirements. If in doubt (or if the
|
||||
checkout fails/the information is not properly saved), try setting the question
|
||||
type to a simple type like "Text (one line)".
|
||||
|
||||
Notes and configuration examples
|
||||
--------------------------------
|
||||
|
||||
Requesting SAML 1.0 and 2.0 attributes from an academic IdP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This requests the ``eduPersonPrincipalName`` (also sometimes called EPPN),
|
||||
``email``, ``givenName`` and ``sn`` both in SAML 1.0 and SAML 2.0 attributes.
|
||||
|
||||
.. sourcecode:: json
|
||||
|
||||
[
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "eduPersonPrincipalName",
|
||||
"isRequired": true,
|
||||
"name": "urn:mace:dir:attribute-def:eduPersonPrincipalName",
|
||||
"nameFormat": "urn:mace:shibboleth:1.0:attributeNamespace:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "eduPersonPrincipalName",
|
||||
"isRequired": true,
|
||||
"name": "urn:oid:1.3.6.1.4.1.5923.1.1.1.6",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "email",
|
||||
"isRequired": true,
|
||||
"name": "urn:mace:dir:attribute-def:mail",
|
||||
"nameFormat": "urn:mace:shibboleth:1.0:attributeNamespace:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "email",
|
||||
"isRequired": true,
|
||||
"name": "urn:oid:0.9.2342.19200300.100.1.3",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "givenName",
|
||||
"isRequired": true,
|
||||
"name": "urn:mace:dir:attribute-def:givenName",
|
||||
"nameFormat": "urn:mace:shibboleth:1.0:attributeNamespace:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "givenName",
|
||||
"isRequired": true,
|
||||
"name": "urn:oid:2.5.4.42",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "sn",
|
||||
"isRequired": true,
|
||||
"name": "urn:mace:dir:attribute-def:sn",
|
||||
"nameFormat": "urn:mace:shibboleth:1.0:attributeNamespace:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "sn",
|
||||
"isRequired": true,
|
||||
"name": "urn:oid:2.5.4.4",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
}
|
||||
]
|
||||
|
||||
skIDentity IdP Metadata URL
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Since the IdP Metadata URL for `skIDentity`_ is not readily documented/visible
|
||||
in their backend, we document it here:
|
||||
``https://service.skidentity.de/fs/saml/metadata``
|
||||
|
||||
Requesting skIDentity attributes for electronic identity cards
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This requests the basic ``eIdentifier``, ``IDType``, ``IDIssuer``, and
|
||||
``NameID`` from the `skIDentity`_ SAML service, which are available for
|
||||
electronic ID cards such as the German ePA/NPA. (Other attributes such as
|
||||
the name and address are available at additional cost from the IdP).
|
||||
|
||||
.. sourcecode:: json
|
||||
|
||||
[
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "eIdentifier",
|
||||
"isRequired": true,
|
||||
"name": "http://www.skidentity.de/att/eIdentifier",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "IDType",
|
||||
"isRequired": true,
|
||||
"name": "http://www.skidentity.de/att/IDType",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "IDIssuer",
|
||||
"isRequired": true,
|
||||
"name": "http://www.skidentity.de/att/IDIssuer",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
},
|
||||
{
|
||||
"attributeValue": [],
|
||||
"friendlyName": "NameID",
|
||||
"isRequired": true,
|
||||
"name": "http://www.skidentity.de/att/NameID",
|
||||
"nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
}
|
||||
]
|
||||
|
||||
.. _pretix.eu: https://pretix.eu
|
||||
.. _Test-, Basic- and Advanced-Federation: https://doku.tid.dfn.de/en:metadata
|
||||
.. _skIDentity: https://www.skidentity.de/
|
||||
@@ -1,8 +1,6 @@
|
||||
Shipping
|
||||
========
|
||||
|
||||
.. note:: This API is only available when the plugin **pretix-shipping** is installed (pretix Hosted and Enterprise only).
|
||||
|
||||
The shipping plugin provides a HTTP API that exposes the various layouts used to generate PDF badges.
|
||||
|
||||
Shipping address resource
|
||||
@@ -1,7 +1,7 @@
|
||||
PDF ticket output
|
||||
=================
|
||||
|
||||
The build-in PDF ticket output plugin provides a HTTP API that exposes the various layouts used
|
||||
The PDF ticket output plugin provides a HTTP API that exposes the various layouts used
|
||||
to generate PDF tickets.
|
||||
|
||||
Resource description
|
||||
@@ -29,8 +29,8 @@ item_assignments list of objects Products this l
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Layout endpoints
|
||||
----------------
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/ticketlayouts/
|
||||
|
||||
@@ -268,75 +268,5 @@ Layout endpoints
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
Ticket rendering endpoint
|
||||
-----------------------------
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/ticketpdfrenderer/render_batch/
|
||||
|
||||
With this API call, you can instruct the system to render a set of tickets into one combined PDF file. To specify
|
||||
which tickets to render, you need to submit a list of "parts". For every part, the following fields are supported:
|
||||
|
||||
* ``orderposition`` (``integer``, required): The ID of the order position to render.
|
||||
* ``override_channel`` (``string``, optional): The sales channel ID to be used for layout selection instead of the
|
||||
original channel of the order.
|
||||
* ``override_layout`` (``integer``, optional): The ticket layout ID to be used instead of the auto-selected one.
|
||||
|
||||
If your input parameters validate correctly, a ``202 Accepted`` status code is returned.
|
||||
The body points you to the download URL of the result. Running a ``GET`` request on that result URL will
|
||||
yield one of the following status codes:
|
||||
|
||||
* ``200 OK`` – The export succeeded. The body will be your resulting file. Might be large!
|
||||
* ``409 Conflict`` – Your export is still running. The body will be JSON with the structure ``{"status": "running"}``. ``status`` can be ``waiting`` before the task is actually being processed. Please retry, but wait at least one second before you do.
|
||||
* ``410 Gone`` – Running the export has failed permanently. The body will be JSON with the structure ``{"status": "failed", "message": "Error message"}``
|
||||
* ``404 Not Found`` – The export does not exist / is expired.
|
||||
|
||||
.. warning:: This endpoint is considered **experimental**. It might change at any time without prior notice.
|
||||
|
||||
.. note:: To avoid performance issues, a maximum number of 1000 parts is currently allowed.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/ticketpdfrenderer/render_batch/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"parts": [
|
||||
{
|
||||
"orderposition": 55412
|
||||
},
|
||||
{
|
||||
"orderposition": 55412,
|
||||
"override_channel": "web"
|
||||
},
|
||||
{
|
||||
"orderposition": 55412,
|
||||
"override_layout": 56
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"download": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/ticketpdfrenderer/download/29891ede-196f-4942-9e26-d055a36e98b8/3f279f13-c198-4137-b49b-9b360ce9fcce/"
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 202: no error
|
||||
:statuscode 400: Invalid input options
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
|
||||
.. _here: https://github.com/pretix/pretix/blob/master/src/pretix/static/schema/pdf-layout.schema.json
|
||||
43
doc/plugins/webinar.rst
Normal file
@@ -0,0 +1,43 @@
|
||||
pretix Webinar
|
||||
==============
|
||||
|
||||
Fetch host URLs
|
||||
---------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/webinars/
|
||||
|
||||
Returns a list of all currently available webinar calls configured for an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/webinars/ 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
|
||||
|
||||
[
|
||||
{
|
||||
"name": "Webinar B – Sept. 8th, 2020",
|
||||
"hosturl": "http://pretix.eu/demo/museum/webinar/host/a9aded3d7bd4df60/30611a34f9fee5d3/"
|
||||
},
|
||||
{
|
||||
"name": "Webinar A – Sept. 8, 2020",
|
||||
"hosturl": "http://pretix.eu/demo/museum/webinar/host/e714x7d4a4a36a04/b9cc444665xxx757/"
|
||||
}
|
||||
]
|
||||
|
||||
:query subevent: Limit the result to the webinar(s) for a specific subevent.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer or event does not exist **or** you have no permission to view it.
|
||||
@@ -1,4 +1,4 @@
|
||||
sphinx==7.4.*
|
||||
sphinx==7.0.*
|
||||
jinja2==3.1.*
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-httpdomain
|
||||
@@ -6,4 +6,5 @@ sphinxcontrib-images
|
||||
sphinxcontrib-jquery
|
||||
sphinxcontrib-spelling==8.*
|
||||
sphinxemoji
|
||||
pygments-markdown-lexer
|
||||
pyenchant==3.2.*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-e ../
|
||||
sphinx==7.4.*
|
||||
sphinx==7.0.*
|
||||
jinja2==3.1.*
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-httpdomain
|
||||
@@ -7,4 +7,5 @@ sphinxcontrib-images
|
||||
sphinxcontrib-jquery
|
||||
sphinxcontrib-spelling==8.*
|
||||
sphinxemoji
|
||||
pygments-markdown-lexer
|
||||
pyenchant==3.2.*
|
||||
|
||||
BIN
doc/screens/event/create_step1.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
doc/screens/event/create_step2.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
doc/screens/event/create_step3.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
doc/screens/event/create_step4.png
Normal file
|
After Width: | Height: | Size: 103 KiB |