Compare commits

...

773 Commits

Author SHA1 Message Date
Richard Schreiber
52d537dec9 Fix initial sidebar display for mobile 2024-08-26 11:22:51 +02:00
Raphael Michel
1879e440a7 Fix isort issue 2024-08-23 15:24:56 +02:00
Mira
f819f0c316 Escape HTML in placeholder samples in mail preview (#4413)
CVE-2024-8113
2024-08-23 14:41:25 +02:00
pretix translation bot
a1db13b75e Update translations (#4410)
* Translations: Update Basque

Currently translated at 0.1% (9 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/eu/

powered by weblate

* Translations: Update Italian

Currently translated at 20.3% (1162 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/it/

powered by weblate

* Translations: Update Basque

Currently translated at 6.0% (345 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/eu/

powered by weblate

* Translations: Update Basque

Currently translated at 45.0% (104 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/eu/

powered by weblate

* Translations: Update Basque

Currently translated at 15.6% (893 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/eu/

powered by weblate

* Translations: Update Basque

Currently translated at 45.4% (105 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/eu/

powered by weblate

---------

Co-authored-by: Albizuri <oier@puntu.eus>
Co-authored-by: Michelangelo <michelangelo.morrillo@gmail.com>
2024-08-23 13:42:48 +02:00
Raphael Michel
6087665775 Email preview: Include prefix in subject (#4395) 2024-08-23 13:42:29 +02:00
Raphael Michel
a6f93b6cf0 Seats API: Add is_available filter (Z#23163419) (#4409)
* Seats API: Add is_available filter (Z#23163419)

* docs
2024-08-21 17:43:13 +02:00
Raphael Michel
b96374fcf6 Do not create duplicate memberships on order changes (Z#23163336) (#4408) 2024-08-21 17:30:42 +02:00
Raphael Michel
eb2ad48089 Docs: Android 4 support dropped for pretixPRINT 2024-08-19 17:26:02 +02:00
dependabot[bot]
64dac504ca Bump markdown from 3.6 to 3.7 (#4402)
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.6 to 3.7.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.6...3.7)

---
updated-dependencies:
- dependency-name: markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-19 14:24:58 +02:00
Raphael Michel
cf15a08712 Link between waiting list settings and maangement (Z#23143161) (#4394) 2024-08-19 13:47:54 +02:00
Raphael Michel
9197274528 Add documentation on CSP for the widget (#4398) 2024-08-19 13:47:47 +02:00
Tinna Sandström
d19176ab41 Translations: Update Swedish
Currently translated at 99.3% (5685 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-08-16 15:08:26 +02:00
Michael Stapelberg
8d8abbd941 Also enable DEBUG for runserver_plus, not just runserver (#4385)
When using runserver_plus from the django-extensions package (for serving a development instance with a TLS certificate), I noticed the DEBUG setting was not set correctly, which resulted in static files not being served correctly.
2024-08-15 14:25:21 +02:00
dependabot[bot]
5142c62e6e Update sentry-sdk requirement from ==2.12.* to ==2.13.* (#4392)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.12.0...2.13.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-15 14:25:07 +02:00
Tinna Sandström
7f7223fcdc Translations: Update Swedish
Currently translated at 99.3% (5685 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-08-15 14:24:57 +02:00
George Hickman
cdde688964 Remove git dir and work tree config from pre-commit hook (#4397)
These variables effectively hardcode the location from which the script
is run.  We shouldn't need these since git should know that it is inside
a repo when run.
2024-08-15 12:42:57 +02:00
George Hickman
233bcaf00e Add a .node-version file (#4396) 2024-08-15 12:42:02 +02:00
Raphael Michel
0a5f3e6dd5 Fix availability of payment methods in time machine (Z#23162163) (#4390) 2024-08-13 12:52:14 +02:00
Raphael Michel
446d24553e Tests: Ignore a deprecation warning 2024-08-13 11:46:11 +02:00
Tinna Sandström
45c32bcb05 Translations: Update Swedish
Currently translated at 99.3% (5684 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-08-09 09:59:11 +02:00
Raphael Michel
5a5090604a Device list: Filter by software brand 2024-08-09 09:55:16 +02:00
Raphael Michel
2b370bde6d PDF layout schema: Add textcontainer 2024-08-08 13:49:23 +02:00
Raphael Michel
024a223ec7 PDF editor: Fix bug in previous change (Z#23162122) 2024-08-08 13:36:50 +02:00
Raphael Michel
022f44ad00 PDF editor: New text element implementation (#4246)
* draft

* almost working

* Widgth adjustment

* Fix crash on empty text

* Change default layouts

* Fix editor bugs

* Update src/pretix/control/templates/pretixcontrol/pdf/index.html

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Show deprecated text on old text

* lockScalingFlip

* Regroup editor controls

* Update src/pretix/static/pretixcontrol/js/ui/main.js

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/static/pretixcontrol/js/ui/main.js

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/static/pretixcontrol/js/ui/main.js

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/static/pretixcontrol/js/ui/editor.js

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Increase default height even further

* Add a small version warning

* Update src/pretix/control/templates/pretixcontrol/pdf/index.html

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/templates/pretixcontrol/pdf/index.html

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-08-07 11:26:47 +02:00
Raphael Michel
a682eab18e Force Django security upgrade 2024-08-07 09:52:51 +02:00
dependabot[bot]
6721762a3f Update kombu requirement from ==5.3.* to ==5.4.* (#4380)
Updates the requirements on [kombu](https://github.com/celery/kombu) to permit the latest version.
- [Release notes](https://github.com/celery/kombu/releases)
- [Changelog](https://github.com/celery/kombu/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/kombu/compare/v5.3.0a1...v5.4.0)

---
updated-dependencies:
- dependency-name: kombu
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-07 09:40:38 +02:00
Raphael Michel
ad443d0eb6 Improve a help text 2024-08-05 12:34:33 +02:00
Raphael Michel
ececd3e572 Order search: Provide typing for answers to questions (Z#23160848) (#4350)
* Order search: Provide typing for answers to questions (Z#23160848)

* Update src/pretix/control/forms/filter.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/control/forms/filter.py

Co-authored-by: Mira <weller@rami.io>

* Apply suggestions from code review

Co-authored-by: Mira <weller@rami.io>

---------

Co-authored-by: Mira <weller@rami.io>
2024-08-05 12:34:15 +02:00
baris gormez
ffc4a76b11 Translations: Update Turkish
Currently translated at 43.7% (2504 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/tr/

powered by weblate
2024-08-05 09:05:19 +02:00
dependabot[bot]
4beb0c2e30 Bump django-filter from 24.2 to 24.3 (#4374)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 24.2 to 24.3.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/24.2...24.3)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 09:05:11 +02:00
dependabot[bot]
48e161d2d4 Bump @babel/core from 7.24.7 to 7.25.2 in /src/pretix/static/npm_dir (#4369)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.24.7 to 7.25.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.2/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 09:24:52 +02:00
Mira
dc1973f4ff Add API endpoint /seats to event (Z#23159536) (#4321)
* add API endpoint /seats to event

* fix logging

* add Seat annotations

* add seats endpoint for subevents

* return ids of occupying objects instead of boolean flags

* wip

* include orderposition instead of order in seat info

* add API documentation

* Apply suggestions from code review

Co-authored-by: Raphael Michel <michel@rami.io>

* Apply suggestions from code review

* Clarify API docs

* add api examples

* add test cases

* require can_view_orders permission for retrieving seats

* improve permission handling

* Revert "improve permission handling"

This reverts commit f32b532cc6.

* improve permission handling (minimal version)

* formatting

* add permission tests

* fix bug

* update permission checks

* Apply suggestions from code review

Co-authored-by: Raphael Michel <michel@rami.io>

* add tests for permission checks

* add tests for expand=voucher and expand=cartposition

* remove unused parameter

* test query count

* codestyle

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-08-02 09:17:46 +02:00
Mira
a0b046d204 Fix #4201, Fix #4271 -- Time machine issues (#4371)
* Fix issue #4201

* Fix issue #4271

* Use time_machine_now() for subevent calendar display
2024-08-02 09:11:07 +02:00
dependabot[bot]
0032f83d93 Update pyjwt requirement from ==2.8.* to ==2.9.* (#4370)
Updates the requirements on [pyjwt](https://github.com/jpadilla/pyjwt) to permit the latest version.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.8.0...2.9.0)

---
updated-dependencies:
- dependency-name: pyjwt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 09:10:25 +02:00
dependabot[bot]
f312200881 Bump @babel/preset-env from 7.24.7 to 7.25.3 in /src/pretix/static/npm_dir (#4368)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.7 to 7.25.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.3/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 09:10:08 +02:00
Raphael Michel
9946da57c2 Stripe: Add Revolut Pay (#4366)
* Stripe: Add Revolut Pay

* Remove is_enabled flag
2024-08-01 17:20:42 +02:00
Raphael Michel
11e04ea3f2 ListExporter: Allow to override CSV encoding in subclass (Z#23160604) (#4367) 2024-08-01 16:20:00 +02:00
Martin Weinelt
9cef63d641 Prevent race condition in directory creation (#4362)
Checking whether a path does not exist before trying to create it does
not follow the Python paradigm of asking for forgiveness, rather than
permission, and opens up a time-of-check to time-of-use race.
2024-08-01 13:12:00 +02:00
pretix translation bot
cb833cc6da Update translations (#4361)
Currently translated at 100.0% (5722 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate

Co-authored-by: pajowu <pajowu@pajowu.de>
2024-08-01 09:32:16 +02:00
dependabot[bot]
5320a69c27 Update sentry-sdk requirement from ==2.11.* to ==2.12.* (#4360)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.11.0...2.12.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 09:31:47 +02:00
dependabot[bot]
510ca67107 Update aiohttp requirement from ==3.9.* to ==3.10.* (#4358)
Updates the requirements on [aiohttp](https://github.com/aio-libs/aiohttp) to permit the latest version.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.0b0...v3.10.0)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 09:31:24 +02:00
Raphael Michel
13720e731e Easier PCI DSS compliance for payment pages (#4273)
* Assign names to compressed scripts

* Make PCI-relevant pages detectable

* Make payment summary markup more consistant to easy work in tracking plugin

* Add docs note
2024-07-31 13:11:38 +02:00
dependabot[bot]
78cfbd6460 Update python-bidi requirement from ==0.5.* to ==0.6.* (#4357)
Updates the requirements on [python-bidi](https://github.com/MeirKriheli/python-bidi) to permit the latest version.
- [Release notes](https://github.com/MeirKriheli/python-bidi/releases)
- [Changelog](https://github.com/MeirKriheli/python-bidi/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/MeirKriheli/python-bidi/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: python-bidi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-31 12:21:48 +02:00
Raphael Michel
a65f94fa85 Autocheckin: Fix handling of mixed orders 2024-07-31 10:05:12 +02:00
Raphael Michel
288f73b735 Bulk voucher creation: Use event default language for default text (#4349)
* Bulk voucher creation: Use event default language for default text

* Update src/pretix/control/forms/vouchers.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Apply suggestions from code review

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Style

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-07-30 16:48:30 +02:00
Raphael Michel
ad33785f4c API: Allow to set seating_allow_blocked_seats_for_channel (Z#23159519) (#4333) 2024-07-30 16:28:08 +02:00
Ismael Menéndez Fernández
bbc175d3d6 Translations: Update Galician
Currently translated at 9.9% (571 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/gl/

powered by weblate
2024-07-30 12:46:46 +02:00
dependabot[bot]
2876ff5549 Update sentry-sdk requirement from ==2.10.* to ==2.11.* (#4334)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.10.0...2.11.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-30 09:26:19 +02:00
Richard Schreiber
ed9caa04fc Fix nup-badges for PDFs with cropbox (Z#23160479) (#4354) 2024-07-30 09:20:55 +02:00
Richard Schreiber
83a8fcaa47 Fix serving media-URLs for development (#4355) 2024-07-30 09:17:27 +02:00
Mira
858a448db5 Fix voucher redemption with time machine [Z#23159226] (#4352)
Redeeming a voucher failed if current time is outside the booking period and the shop was accessed via time machine.
2024-07-30 09:14:36 +02:00
Richard Schreiber
58b803539b Fix auto-linking error-inputs self-referencing (Z#23159088) (#4351) 2024-07-30 09:14:06 +02:00
Raphael Michel
6c92c5bacf Translations: Fix typo 2024-07-29 13:27:27 +02:00
Raphael Michel
f0089f20fb Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5722 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-29 13:27:03 +02:00
Raphael Michel
cb2d056afd Translations: Update German
Currently translated at 100.0% (5722 of 5722 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-07-29 13:27:03 +02:00
Raphael Michel
afb115c9a2 Remove static3 and dj-static (#4346) 2024-07-29 13:17:50 +02:00
Raphael Michel
bb92ffe4eb Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-07-29 12:52:25 +02:00
Ismael Menéndez Fernández
8da8e2f43d Translations: Update Galician
Currently translated at 10.0% (570 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/gl/

powered by weblate
2024-07-29 12:52:00 +02:00
Raphael Michel
cab360bdb6 Move auto check-in to plugin with more functionality (#4331)
* Move auto check-in to plugin with more functionality

* Rename field

* Add to MANIFEST.in
2024-07-29 09:46:53 +02:00
Raphael Michel
c6a2ae3783 Docs: Remove pygments-markdown-lexer (unmaintained, and now in pygments core) 2024-07-29 09:45:53 +02:00
Raphael Michel
26ec9dcf6c Downgrade setuptools 2024-07-29 09:41:05 +02:00
Raphael Michel
c0832098ef Bump version to 2024.8.0.dev0 2024-07-26 17:04:23 +02:00
Raphael Michel
fa3ac69b8e API: Allow to filter enabled webhooks (Z#23160605) (#4336)
* API: Allow to filter enabled webhooks (Z#23160605)

* Fix naming

* Fix isort
2024-07-26 17:04:12 +02:00
Raphael Michel
17f1d571b0 API: Allow querying invoices with multiple order codes (Z#23158921) (#4332) 2024-07-26 16:32:29 +02:00
Raphael Michel
a692940397 Bump version to 2024.7.0 2024-07-26 14:36:20 +02:00
Raphael Michel
7f2ec51c64 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5700 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-26 14:34:02 +02:00
Raphael Michel
aba59a391c Translations: Update German
Currently translated at 100.0% (5700 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-07-26 14:34:02 +02:00
Ismael Menéndez Fernández
a819b8bb71 Translations: Update Galician
Currently translated at 9.9% (568 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/gl/

powered by weblate
2024-07-26 14:34:02 +02:00
Raphael Michel
8a3b18fbd2 Translations: Update German
Currently translated at 100.0% (5700 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-07-26 14:34:02 +02:00
Raphael Michel
dd444299f0 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5700 of 5700 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-26 14:34:02 +02:00
Raphael Michel
3ee5e9cfbc Docs: Add migration note 2024-07-26 13:54:23 +02:00
Raphael Michel
f660f35766 Fix an English word usage 2024-07-26 13:54:16 +02:00
Raphael Michel
42e26738e5 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-07-26 09:19:14 +02:00
Raphael Michel
7c43f115b2 Docs: Update Android version policy 2024-07-25 13:18:37 +02:00
dependabot[bot]
f055a598ce Bump django-compressor from 4.5 to 4.5.1 (#4330)
Bumps [django-compressor](https://github.com/django-compressor/django-compressor) from 4.5 to 4.5.1.
- [Changelog](https://github.com/django-compressor/django-compressor/blob/develop/docs/changelog.txt)
- [Commits](https://github.com/django-compressor/django-compressor/compare/4.5...4.5.1)

---
updated-dependencies:
- dependency-name: django-compressor
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-24 14:38:54 +02:00
Raphael Michel
9138464896 Translations: Delete Abron 2024-07-24 14:38:38 +02:00
Martin Gross
479f51a84c Apply suggestions from code review
Co-authored-by: robbi5 <richt@rami.io>
Co-authored-by: Felix Rindt <felix@rindt.me>
2024-07-24 14:23:12 +02:00
Martin Gross
a3ac54d419 Docs: Add documentation on GetYourGuide 2024-07-24 14:23:12 +02:00
Raphael Michel
b2841e5c61 SSO Providers: Use redacted field for secret key 2024-07-23 16:26:37 +02:00
dependabot[bot]
3009f50d51 Update pytest requirement from ==8.2.* to ==8.3.* (#4324)
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.0.dev0...8.3.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 15:54:51 +02:00
Gero Nagel
ff3a49ab2a Docs: Remove redundant package dependency (#4327)
* remove naming python3-dev twice

* Revert "ListExporter: Do not create excel sheets with more than 30 characters"

This reverts commit ca3802da90.

* Revert "remove naming python3-dev twice"

This reverts commit 7adf2d65e8.

* Revert "Revert "ListExporter: Do not create excel sheets with more than 30 characters""

This reverts commit d289dc0d1d.

* delete naming pyhton3-dev twice
2024-07-23 15:54:37 +02:00
Raphael Michel
19f3fbc7e8 Order data export: Include ID of parent position of add-ons 2024-07-23 15:52:55 +02:00
dependabot[bot]
bb9b9ac9aa Update pypdf requirement from ==4.2.* to ==4.3.* (#4307)
Updates the requirements on [pypdf](https://github.com/py-pdf/pypdf) to permit the latest version.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/4.2.0...4.3.0)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raphael Michel <michel@rami.io>
2024-07-23 13:48:11 +02:00
dependabot[bot]
d7f6befb5b Bump @babel/preset-env from 7.24.6 to 7.24.7 in /src/pretix/static/npm_dir (#4281)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.6 to 7.24.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.7/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 13:30:58 +02:00
dependabot[bot]
2287be2009 Update sphinx requirement from ==7.3.* to ==7.4.* (#4306)
Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx) to permit the latest version.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.3.0...v7.4.4)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 13:29:18 +02:00
dependabot[bot]
0480b6873d Update sentry-sdk requirement from ==2.5.* to ==2.10.* (#4305)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.5.0...2.10.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 13:29:11 +02:00
dependabot[bot]
711f08c9e8 Update python-bidi requirement from ==0.4.* to ==0.5.* (#4325)
* Update python-bidi requirement from ==0.4.* to ==0.5.*

Updates the requirements on [python-bidi](https://github.com/MeirKriheli/python-bidi) to permit the latest version.
- [Release notes](https://github.com/MeirKriheli/python-bidi/releases)
- [Changelog](https://github.com/MeirKriheli/python-bidi/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/MeirKriheli/python-bidi/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: python-bidi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update import

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raphael Michel <michel@rami.io>
2024-07-23 13:27:15 +02:00
Alberto Ortega
d18914fcca Translations: Update Spanish
Currently translated at 88.5% (5041 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-07-23 13:27:07 +02:00
Raphael Michel
2411144262 Ignore a deprecation warning in pypdf 2024-07-23 13:06:00 +02:00
test\"img src=x onerror=prompt(document.cookie)
2f02d35a52 Translations: Add Abron 2024-07-23 11:56:05 +02:00
Richard Schreiber
71e82fda81 Auto-fill questions from invoice address (Z#23143497) (#4303)
* Match invoice address to questions by id, placeholder and label

* make label-text extraction more robust

* match actual label as well
2024-07-23 11:54:10 +02:00
Raphael Michel
ca3802da90 ListExporter: Do not create excel sheets with more than 30 characters 2024-07-23 09:35:34 +02:00
JnnisCanis
2c68b9e895 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-22 10:07:01 +02:00
bokor-rami-io
01092498f4 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-22 10:07:01 +02:00
Raphael Michel
fd841ed66d Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-22 10:07:01 +02:00
Raphael Michel
04cbccb536 Translations: Update German
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-07-22 10:07:01 +02:00
Raphael Michel
b8ea93de1e Fix ticket_download_require_validated_email after sales channel change 2024-07-22 09:38:35 +02:00
Richard Schreiber
c49f42301c Fix file-type check for product image 2024-07-19 12:44:49 +02:00
Reece Needham
2ae0a16e67 Translations: Update Spanish
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2024-07-19 11:52:27 +02:00
Reece Needham
6b06fdf822 Translations: Update Spanish
Currently translated at 88.6% (5045 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-07-19 11:52:27 +02:00
Reece Needham
ea3f4e5f62 Translations: Update Spanish
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2024-07-19 11:52:27 +02:00
Reece Needham
d71c23f7e0 Translations: Update Spanish
Currently translated at 87.5% (4983 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-07-19 11:52:27 +02:00
Nikolai
5ed7b0032b Translations: Update Danish
Currently translated at 49.4% (2815 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-19 11:52:27 +02:00
Martin Gross
a77f2d01a7 CartManager: Allow to explicitly set an order expiration 2024-07-19 11:38:36 +02:00
Raphael Michel
ca4f511cde Voucher import: Fix subevent column 2024-07-19 10:56:17 +02:00
Raphael Michel
83b1c2ea7e Do not take "optional" as part of error message label (#4309) 2024-07-18 14:57:25 +02:00
Richard Schreiber
c91eb2e20d Set cursor to not-allowed on labels for disabled checkboxes 2024-07-18 11:54:43 +02:00
Richard Schreiber
bfb480a288 UI: in plugin-list only show border-top when necessary (#4314) 2024-07-18 11:43:24 +02:00
Richard Schreiber
22e2143623 API: add api_meta to order 2024-07-18 10:01:03 +02:00
Raphael Michel
9e61f7f978 API: Fix admin permission issue in subevent endpoint 2024-07-18 09:44:30 +02:00
Raphael Michel
092de9e3c4 Add webhook for pretix.event.order.deleted (Z#23159520) (#4310) 2024-07-17 17:15:35 +02:00
Richard Schreiber
f0822d3c27 Docs: add help for HTTP-COOP: same-origin, widget and Paypal (#4311)
* Docs: add help for HTTP-COOP, widget and Paypal

* fix typo Paypal => PayPal

Co-authored-by: Raphael Michel <michel@rami.io>

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-07-17 16:12:17 +02:00
dependabot[bot]
6fc47ca3b6 Update django-hijack requirement from ==3.5.* to ==3.6.* (#4290)
Updates the requirements on [django-hijack](https://github.com/django-hijack/django-hijack) to permit the latest version.
- [Release notes](https://github.com/django-hijack/django-hijack/releases)
- [Changelog](https://github.com/django-hijack/django-hijack/blob/master/docs/release-button.png)
- [Commits](https://github.com/django-hijack/django-hijack/compare/3.5.0...3.6.0)

---
updated-dependencies:
- dependency-name: django-hijack
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-17 14:27:42 +02:00
Raphael Michel
3716a686f5 Translations: Add Basque 2024-07-17 14:27:30 +02:00
Erik Löfman
9c0c77958e Translations: Update Swedish
Currently translated at 99.9% (5685 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-17 14:27:30 +02:00
Nikolai
6154a44274 Translations: Update Danish
Currently translated at 47.9% (2727 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-17 14:27:30 +02:00
Erik Löfman
d5aff10297 Translations: Update Swedish
Currently translated at 98.5% (5610 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-17 14:27:30 +02:00
Erik Löfman
846e39a652 Translations: Update Swedish
Currently translated at 94.4% (5374 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-17 14:27:30 +02:00
Mira
75d37b2a37 Don't exclude localization PRs from test CI action (#4276)
* Don't exclude localization PRs from test CI action

* Update tests.yml

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-07-17 14:23:39 +02:00
Raphael Michel
2a0c3da8c4 Fix N+1 query found by sentry (PRETIXEU-AC2) 2024-07-16 11:25:48 +02:00
Martin Gross
fb7f4d1160 Control/Waitlist: Add help_text to waiting_list_limit_per_user (Z#23158537) 2024-07-15 13:39:31 +02:00
Erik Löfman
5c8817f0c3 Translations: Update Swedish
Currently translated at 94.2% (5364 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
7663bf7994 Translations: Update Swedish
Currently translated at 87.3% (4972 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
ea8f74f8aa Translations: Update Swedish
Currently translated at 87.3% (4970 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
7b34701449 Translations: Update Danish
Currently translated at 46.1% (2625 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Dirk-jan mollema
06f4bfea24 Translations: Update Dutch
Currently translated at 86.5% (4925 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
e2862a98a0 Translations: Update Danish
Currently translated at 45.2% (2572 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
82f4feadc3 Translations: Update Swedish
Currently translated at 81.8% (4657 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
906222c7d3 Translations: Update Danish
Currently translated at 66.2% (153 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
7ce2089ca8 Translations: Update Danish
Currently translated at 44.4% (2532 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
2133584ed2 Translations: Update Swedish
Currently translated at 75.2% (4280 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
c3c50d7205 Translations: Update Danish
Currently translated at 41.6% (2369 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
4f7a41a4b2 Translations: Update Swedish
Currently translated at 71.2% (4055 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
93fd79ab33 Translations: Update Danish
Currently translated at 65.8% (152 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
59595c2f10 Translations: Update Danish
Currently translated at 40.9% (2332 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Erik Löfman
91c6d09f0b Translations: Update Swedish
Currently translated at 64.8% (3688 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-15 09:46:49 +02:00
Nikolai
570a818129 Translations: Update Danish
Currently translated at 35.5% (2025 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-15 09:46:49 +02:00
Martin Gross
d63e2ebe2d Chore/flake8: Remove extra blank line 2024-07-12 12:34:39 +02:00
Martin Gross
884c97d62a Stripe/SOFORT: Move SOFORT from iFrame to proper redirect (Z#23158598) 2024-07-12 12:30:37 +02:00
Mira
032e958a00 Fix test cases for checkinlist export (#4301) 2024-07-12 11:58:10 +02:00
Mira
7b16dfefbc New column and sort options for check-in-list export (#4300)
Allow check-in-list export to by sorted by order datetime (Z#23158159)
Add check-in text to export
2024-07-12 10:37:22 +02:00
Richard Schreiber
8a5b13dee9 Waitinglist: show time for subevent in overview 2024-07-09 15:37:51 +02:00
Richard Schreiber
d7dde8c23e Fix CSS-color in alert-danger icon 2024-07-09 10:17:20 +02:00
Richard Schreiber
1e2f93fbc5 Waitinglist: add time to subevent dropdown when sending vouchers (#4296) 2024-07-09 09:28:19 +02:00
Richard Schreiber
493fc03686 Fix PayPal CSP img-src 2024-07-09 09:26:46 +02:00
Raphael Michel
8d6d885f6e API: Add various filtering options
* API: Add various filtering options (#23158339)

* fix query-param description

* simplify payment provider qs-filter

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-07-08 21:31:54 +02:00
Martin Gross
2aa989c293 PPv2: Do not fail hard on refunds that are based on manually confirmed payments (Fixes: #PRETIXEU-AC1) 2024-07-04 15:12:53 +02:00
dependabot[bot]
06b226f40f Update pillow requirement from ==10.3.* to ==10.4.* (#4280)
Updates the requirements on [pillow](https://github.com/python-pillow/Pillow) to permit the latest version.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.3.0...10.4.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-04 14:46:46 +02:00
Raphael Michel
73038b0d97 Fix enforcement of restricted plugins (#4286) 2024-07-03 17:14:03 +02:00
Erik Löfman
4513e31f0d Translations: Update Swedish
Currently translated at 63.0% (3585 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-03 17:05:45 +02:00
Raphael Michel
d34175114b Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-07-03 17:05:45 +02:00
Raphael Michel
b2c71b47ce Translations: Update German
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-07-03 17:05:45 +02:00
Raphael Michel
a889abc52b Unify terminology choice Ticketshop (German) 2024-07-03 13:41:09 +02:00
Raphael Michel
8c01b2a469 API: Fix crash in creating variations 2024-07-03 12:37:41 +02:00
Raphael Michel
720c7fd7bb Fix crash in event cloning (PRETIXEU-ABX) 2024-07-03 11:52:57 +02:00
Raphael Michel
6ae6eba4de API: Add details of seats (#4282) 2024-07-03 09:48:59 +02:00
Raphael Michel
a173e347ea Optimize availability queries 2024-07-02 18:29:44 +02:00
Raphael Michel
94d13e4cdd API: Raise the right validation error (PRETIXEU-ABV) 2024-07-02 17:49:09 +02:00
Raphael Michel
e618441231 API: Fix crash expanding variations 2024-07-02 14:44:35 +02:00
Raphael Michel
cd57f1f024 API: Fix creation of embedded variations with explicit sales channels 2024-07-02 09:25:19 +02:00
Raphael Michel
075b9c187f Item list: Fix exclusive tax rules 2024-07-02 09:03:57 +02:00
Erik Löfman
d9f46cb817 Translations: Update Swedish
Currently translated at 59.2% (3374 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-07-01 18:24:27 +02:00
Anarion Dunedain
2892d16861 Translations: Update Polish
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-07-01 18:24:27 +02:00
Nikolai
9128624d68 Translations: Update Danish
Currently translated at 34.8% (1985 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-07-01 18:24:27 +02:00
Raphael Michel
d2cf8f801d Sales channels: Fix update view 2024-07-01 17:50:27 +02:00
Raphael Michel
682d0f886d Fix order change edge case (PRETIXEU-ABH) 2024-07-01 14:39:34 +02:00
Raphael Michel
d2cbd41a19 Fix ticket preview (PRETIXEU-ABF) 2024-07-01 14:38:25 +02:00
Raphael Michel
828f4e3168 Fix isort and docs test 2024-07-01 11:46:46 +02:00
Raphael Michel
e691afdd34 Add auto-generated migration 2024-07-01 11:26:55 +02:00
Raphael Michel
add90b08ec Export: Fix sales channels in JSON export 2024-07-01 11:22:18 +02:00
Raphael Michel
4539c6523b Fix failing tests 2024-07-01 09:24:42 +02:00
Raphael Michel
3453818c16 Fix email layout preview (PRETIXEU-AB9) 2024-07-01 08:56:36 +02:00
Raphael Michel
e5725d6d33 Fix statistics view (PRETIXEU-AB5) 2024-07-01 08:51:23 +02:00
Raphael Michel
0cda1aeaaf Remove nl_BE again 2024-06-30 23:44:55 +02:00
Raphael Michel
769c451bcb Docs: Fix incorrect argument name 2024-06-30 23:34:17 +02:00
Raphael Michel
5b60928205 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2024-06-30 23:13:36 +02:00
Raphael Michel
b05f3a449d Translations: Update German
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2024-06-30 23:13:36 +02:00
Raphael Michel
3262f2ba84 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-30 23:13:36 +02:00
Raphael Michel
fe9d8e58a1 Translations: Update German
Currently translated at 100.0% (5690 of 5690 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-30 23:13:36 +02:00
Raphael Michel
6706dbb4db Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-06-30 20:56:24 +02:00
Raphael Michel
87632ff8c5 Merge pull request #4274 from pretix-translations/weblate-pretix-pretix 2024-06-30 20:55:22 +02:00
Weblate
2278dbdc4a Merge remote-tracking branch 'origin/master' 2024-06-30 20:54:15 +02:00
Raphael Michel
e4e6cc0fcc Revert "Update po files"
This reverts commit ea73977c37.
2024-06-30 20:53:13 +02:00
Raphael Michel
ea73977c37 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-06-30 20:44:34 +02:00
Raphael Michel
4fb5c6bef0 New implementation of sales channels (#4111)
Co-authored-by: Martin Gross <gross@rami.io>
2024-06-30 19:24:30 +02:00
Raphael Michel
95511b0330 Remove X-XSS-Protection, no longer supported by any browser 2024-06-29 19:25:34 +02:00
Raphael Michel
3340599aec Phase out giropay support (#4266) 2024-06-28 16:17:45 +02:00
pretix translation bot
e9a52d07d1 Update translations (#4265)
Co-authored-by: Nikolai <nikolai@lengefeldt.de>
Co-authored-by: Anarion Dunedain <anarion80@gmail.com>
Co-authored-by: Erik Löfman <erik@disruptiveventures.se>
Co-authored-by: Kristian Feldsam <feldsam@gmail.com>
2024-06-28 12:54:45 +02:00
Erik Löfman
0a00a35ab1 Translations: Update Swedish
Currently translated at 57.1% (3237 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-28 12:45:58 +02:00
Nikolai
24d8dc6c76 Translations: Update Danish
Currently translated at 31.3% (1777 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-28 12:45:58 +02:00
Erik Löfman
a9d48eaafe Translations: Update Swedish
Currently translated at 87.0% (201 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/sv/

powered by weblate
2024-06-28 12:45:58 +02:00
Erik Löfman
bb959fa494 Translations: Update Swedish
Currently translated at 56.6% (3210 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
6126309429 Translations: Update Polish
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/pl/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
29b49ca82f Translations: Update Polish
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:58 +02:00
Nikolai
7b7b83cb3e Translations: Update Danish
Currently translated at 31.3% (1774 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-28 12:45:58 +02:00
Erik Löfman
6bb2b3425d Translations: Update Swedish
Currently translated at 52.8% (2991 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
182d30ffb7 Translations: Update Polish
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
844c291575 Translations: Update Polish
Currently translated at 97.9% (5550 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:58 +02:00
Kristian Feldsam
ecdb1a8e09 Translations: Update Slovak
Currently translated at 2.5% (6 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/sk/

powered by weblate
2024-06-28 12:45:58 +02:00
Kristian Feldsam
6c6e5d5af6 Translations: Update Slovak
Currently translated at 93.1% (5276 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sk/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
c33853173b Translations: Update Polish
Currently translated at 91.5% (5186 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:58 +02:00
Erik Löfman
5f90bf80b8 Translations: Update Swedish
Currently translated at 52.7% (2985 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-28 12:45:58 +02:00
Anarion Dunedain
0ba246846b Translations: Update Polish
Currently translated at 85.7% (4859 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:57 +02:00
Erik Löfman
88ea04551e Translations: Update Swedish
Currently translated at 45.9% (2602 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-28 12:45:57 +02:00
Anarion Dunedain
2bfd8e17b0 Translations: Update Polish
Currently translated at 78.9% (4469 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-28 12:45:57 +02:00
Nikolai
1379e5f723 Translations: Update Danish
Currently translated at 31.1% (1766 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-28 12:45:57 +02:00
Martin Gross
9fcaa3d730 Languages: On second thought, make Swedish a regular community-language. 2024-06-28 12:45:52 +02:00
Martin Gross
22d92025c9 Languages: Adding Swedish to incubating languages 2024-06-28 12:33:32 +02:00
Richard Schreiber
2b84c8d7a7 Fix CSS vars naming prefix 2024-06-28 09:36:26 +02:00
Richard Schreiber
25ba2f1145 Add signal seatingframe_html_head (#4270) 2024-06-27 10:46:26 +02:00
Richard Schreiber
ae8ff60964 Fix missing CSS in seatingframe (#4269) 2024-06-27 10:20:09 +02:00
Raphael Michel
9fe6916ab5 Item index: use internal category names again 2024-06-26 15:25:04 +02:00
Raphael Michel
634263f1ba Item form: Validate empty dynamic validity 2024-06-26 09:44:49 +02:00
dependabot[bot]
67265e94a0 Update importlib-metadata requirement from ==7.* to ==8.* (#4264)
Updates the requirements on [importlib-metadata](https://github.com/python/importlib_metadata) to permit the latest version.
- [Release notes](https://github.com/python/importlib_metadata/releases)
- [Changelog](https://github.com/python/importlib_metadata/blob/main/NEWS.rst)
- [Commits](https://github.com/python/importlib_metadata/compare/v7.0.0...v8.0.0)

---
updated-dependencies:
- dependency-name: importlib-metadata
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 09:27:04 +02:00
dependabot[bot]
0fa2e9b5dd Update webauthn requirement from ==2.1.* to ==2.2.* (#4263)
Updates the requirements on [webauthn](https://github.com/duo-labs/py_webauthn) to permit the latest version.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v2.1.0...v2.2.0)

---
updated-dependencies:
- dependency-name: webauthn
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 09:26:58 +02:00
Raphael Michel
c99d93a078 CSS: Fix minor bugs 2024-06-25 15:55:48 +02:00
Raphael Michel
9e20fac0da CSS: Fix handling of white background 2024-06-25 15:22:16 +02:00
Raphael Michel
3e4ccc53be Fix primary color in control 2024-06-25 14:28:47 +02:00
Mira Weller
ce88dfa530 add missing semicolon 2024-06-25 14:23:27 +02:00
Raphael Michel
f0a06cd9fe Replace SCSS compilation with CSS variables (#4191)
* Replace SCSS compilation with CSS variables

* Update tests

* Update src/pretix/presale/style.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/presale/context.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/presale/views/widget.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/presale/context.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/static/pretixbase/scss/_variables.scss

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Last minor changes

* Rename file

---------

Co-authored-by: Mira <weller@rami.io>
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-06-25 13:01:20 +02:00
Erik Löfman
7672e6274d Translations: Update Swedish
Currently translated at 39.4% (2232 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-25 13:01:13 +02:00
Anarion Dunedain
061f578b29 Translations: Update Polish
Currently translated at 76.7% (4346 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-25 13:01:13 +02:00
Erik Löfman
79f8501a09 Translations: Update Swedish
Currently translated at 37.8% (2145 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-25 13:01:13 +02:00
Erik Löfman
c5237b5021 Translations: Update Swedish
Currently translated at 36.3% (2057 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-25 13:01:13 +02:00
Anarion Dunedain
0d6f7e74a3 Translations: Update Polish
Currently translated at 76.4% (4332 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-25 13:01:13 +02:00
Reece Needham
21bd4a86a7 Translations: Update Spanish
Currently translated at 100.0% (231 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2024-06-25 13:01:13 +02:00
Reece Needham
750f641018 Translations: Update Spanish
Currently translated at 87.6% (4966 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-06-25 13:01:13 +02:00
Felix Hartnagel
2a385d14c4 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-25 13:01:13 +02:00
Felix Hartnagel
6a7ab1bdf5 Translations: Update German
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-25 13:01:13 +02:00
Mira
a73c4ad937 Improve List Sorting UI (#4215)
Improve product list UI (allow move between categories, more useful columns and links)
and hide "move up/down" arrows in lists by default if drag-drop is available
2024-06-25 12:54:11 +02:00
Raphael Michel
043e2eb9cf Order denial email: Use correct language for context 2024-06-25 11:57:42 +02:00
Raphael Michel
c0fb93ea3b Waiting list: Add additional explanation (Z#23157006) 2024-06-25 11:31:16 +02:00
Raphael Michel
4f9297e7d8 Show minimal check-in status in order export (Z#23154920) (#4223)
* Show minimal check-in status in order export (Z#23154920)

* Update src/pretix/helpers/database.py

Co-authored-by: Mira <weller@rami.io>

* Review note

---------

Co-authored-by: Mira <weller@rami.io>
2024-06-24 17:34:10 +02:00
Erik Löfman
70b48fdd4b Translations: Update Swedish
Currently translated at 35.2% (1994 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-24 17:20:24 +02:00
Anarion Dunedain
e7b5317431 Translations: Update Polish
Currently translated at 75.1% (4259 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 17:20:24 +02:00
Mira
63ef2e70e2 Translations: Update Spanish
Currently translated at 75.3% (174 of 231 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2024-06-24 17:20:24 +02:00
Mira
c4db2a48b6 Translations: Update Spanish
Currently translated at 87.6% (4964 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-06-24 17:20:24 +02:00
Reece Needham
de255b021e Translations: Update Spanish
Currently translated at 87.6% (4964 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-06-24 17:20:24 +02:00
Raphael Michel
d3fce71b7f Bump version to 2024.7.0.dev0 2024-06-24 11:05:53 +02:00
Raphael Michel
37dea068ce Bump version to 2024.6.0 2024-06-24 11:04:38 +02:00
Raphael Michel
b5ef49cd3c Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-24 11:00:19 +02:00
Raphael Michel
245c5972c6 Translations: Update German
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-24 11:00:19 +02:00
Raphael Michel
6597977752 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-24 11:00:19 +02:00
Raphael Michel
580137577e Translations: Update German
Currently translated at 100.0% (5664 of 5664 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-24 11:00:19 +02:00
Raphael Michel
a09550ce02 Translations:Add TWINT to wordlist 2024-06-24 10:55:26 +02:00
Raphael Michel
1b444b780d Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-06-24 10:20:56 +02:00
Anarion Dunedain
f41d8bb761 Translations: Update Polish
Currently translated at 68.3% (3850 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Maciej Szymczak
365dbe7a14 Translations: Update Polish
Currently translated at 63.5% (3582 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Anarion Dunedain
bf6078efb6 Translations: Update Polish
Currently translated at 63.5% (3582 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Anarion Dunedain
695b9a2ed6 Translations: Update Polish
Currently translated at 63.5% (3579 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Anarion Dunedain
25a15069ed Translations: Update Polish
Currently translated at 51.8% (2921 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Anarion Dunedain
11a4ea7b77 Translations: Update Polish
Currently translated at 100.0% (229 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Anarion Dunedain
4e5e7df201 Translations: Update Polish
Currently translated at 49.5% (2789 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-24 09:24:57 +02:00
Raphael Michel
8f515aa327 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (229 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2024-06-24 09:24:57 +02:00
Tinna Sandström
dbc7fda2f8 Translations: Update Swedish
Currently translated at 27.0% (1522 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-24 09:24:57 +02:00
Erik Löfman
5e686674ae Translations: Update Swedish
Currently translated at 27.0% (1522 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-24 09:24:57 +02:00
Raphael Michel
5660cd7f93 Translations: Update German
Currently translated at 100.0% (229 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2024-06-24 09:24:57 +02:00
Raphael Michel
a7a33ed165 Voucher bulk form: Strip spaces from email addresses before validation 2024-06-20 17:16:21 +02:00
Richard Schreiber
9ffdf979f4 PDF: ignore outline, annots, etc. when merging background-pdf (#4249) 2024-06-20 12:07:04 +02:00
Raphael Michel
7338381e58 Stripe: Support for TWINT (#4216)
* Stripe: Support for TWINT

* Update src/pretix/plugins/stripe/payment.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-06-20 10:22:43 +02:00
Raphael Michel
ce06672334 Event list: Do not carry page through filter form 2024-06-19 18:19:51 +02:00
Raphael Michel
223f095611 Add Slovak and Catalan to selectable languages 2024-06-19 18:11:41 +02:00
dependabot[bot]
b625dc9ec8 Bump braces from 3.0.2 to 3.0.3 in /src/pretix/static/npm_dir (#4230)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 18:01:25 +02:00
dependabot[bot]
50c4a1c376 Update flake8 requirement from ==7.0.* to ==7.1.* (#4240)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 18:01:18 +02:00
dependabot[bot]
6fd2e42426 Bump django-compressor from 4.4 to 4.5 (#4241)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 18:00:56 +02:00
Erik Löfman
da651df4f0 Translations: Update Swedish
Currently translated at 25.7% (1450 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-19 18:00:44 +02:00
Nikolai
a6f527e32d Translations: Update Danish
Currently translated at 31.3% (1764 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-19 18:00:44 +02:00
Thilo-Alexander Ginkel
3ea61fbd1f Translations: Update German
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-19 18:00:44 +02:00
simonD
6a959d4220 Translations: Update French
Currently translated at 96.5% (5440 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-06-19 18:00:44 +02:00
L. Pereira
92959dbb1f Translations: Update Portuguese (Brazil)
Currently translated at 12.9% (730 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pt_BR/

powered by weblate
2024-06-19 18:00:44 +02:00
Anarion Dunedain
6d6f3c4af8 Translations: Update Polish
Currently translated at 39.9% (2251 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-06-19 18:00:44 +02:00
Thilo-Alexander Ginkel
8d14a285ca Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-19 18:00:44 +02:00
Raphael Michel
a6b8cd8a54 Stripe: Move Multibanco to payment intents (#4243) 2024-06-19 18:00:23 +02:00
Martin Gross
cb95cdc6ce item_forms: Allow signals to return None (#4237)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-06-18 16:24:39 +02:00
Erik Löfman
cc7b00e206 Translations: Update Swedish
Currently translated at 21.3% (1203 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-18 15:34:40 +02:00
Kristian Feldsam
136c54b9a8 Translations: Update Slovak
Currently translated at 92.7% (5226 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sk/

powered by weblate
2024-06-18 15:34:40 +02:00
Kristian Feldsam
28ba434e45 Translations: Update Slovak
Currently translated at 0.4% (1 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/sk/

powered by weblate
2024-06-18 15:34:40 +02:00
Erik Löfman
09320093ad Translations: Update Swedish
Currently translated at 21.2% (1200 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-17 10:15:25 +02:00
Kristian Feldsam
89cfab6cad Translations: Update Slovak
Currently translated at 91.0% (5129 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sk/

powered by weblate
2024-06-17 10:15:25 +02:00
alemairebe
a180ce4c51 Translations: Update French
Currently translated at 96.6% (5443 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-06-17 10:15:25 +02:00
Raphael Michel
1200274ebf Export: Do not rely on cached answer option values (Z#23152831) (#4225)
* Export: Do not rely on cached answer option values

* refactor duplicate code

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-06-17 10:12:15 +02:00
Raphael Michel
877401d8c0 Remove subevent.items (#4220) 2024-06-14 14:49:55 +02:00
Martin Gross
44170c1b93 Doc: Add missing backquote in dev/structure (ref #4222) 2024-06-14 12:31:35 +02:00
Renne Rocha
ce34bd0a13 Translations: Update Portuguese (Brazil)
Currently translated at 11.9% (672 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pt_BR/

powered by weblate
2024-06-14 12:03:39 +02:00
Erik Löfman
b58f05efd0 Translations: Update Swedish
Currently translated at 21.1% (1190 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-14 12:03:39 +02:00
Tinna Sandström
3ac70e6e3a Translations: Update Swedish
Currently translated at 21.1% (1190 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-14 12:03:39 +02:00
Raphael Michel
90123d6a58 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-14 12:03:39 +02:00
Raphael Michel
48a3984db6 Translations: Update German
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-14 12:03:39 +02:00
simonD
fe6ee4437f Translations: Update French
Currently translated at 96.6% (5443 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-06-14 12:03:39 +02:00
simonD
f470389cd8 Translations: Update French
Currently translated at 93.0% (213 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/fr/

powered by weblate
2024-06-14 12:03:39 +02:00
simonD
c848594c21 Translations: Update French
Currently translated at 96.5% (5442 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-06-14 12:03:39 +02:00
Raphael Michel
e9a95b0b09 Add system report for pretix Enterprise (#4213)
* Add system report for pretix Enterprise

* Update src/pretix/control/sysreport.py

Co-authored-by: Mira <weller@rami.io>

* ADd missing license header

---------

Co-authored-by: Mira <weller@rami.io>
2024-06-13 17:08:36 +02:00
Richard Schreiber
3b48b0782d PDF: when merging bg.pdf with fg.pdf use the higher PDF-version (#4171) 2024-06-11 12:16:57 +02:00
Tinna Sandström
b55bd8f75a Translations: Update Swedish
Currently translated at 20.8% (1174 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-11 09:00:13 +02:00
Raphael Michel
39caadb335 Compatibility of safe_openpyxl with openpyxl==3.1.3 2024-06-10 17:19:29 +02:00
Mira
dd6ebd7a48 Improve validation of email templates (#4184)
* Improve validation of email templates

* simplify SafeFormatter (skip attribute access code path altogether instead of blocklisting characters)

* let SafeFormatter optionally raise on missing key

* simplify placeholder validation

* rename parameter

* Remove unused import

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-06-10 16:41:52 +02:00
Raphael Michel
ab576bb643 Update sentry-sdk requirement from ==1.45.* to ==2.5.* (#4176)
* Update sentry-sdk requirement from ==1.45.* to ==2.3.*

* Review notes
2024-06-10 16:25:08 +02:00
dependabot[bot]
8bc16af36e Bump @babel/core from 7.24.5 to 7.24.7 in /src/pretix/static/npm_dir (#4209)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.24.5 to 7.24.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.7/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 15:13:24 +02:00
Raphael Michel
537044bdc8 Bank transfer: Ignore checksum for blocklist (Z#23154934) (#4194)
* Bank transfer: Ignore checksum for blocklist (Z#23154934)

* Update src/pretix/plugins/banktransfer/payment.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-06-10 14:49:51 +02:00
dependabot[bot]
1ac7d03bb8 Bump pug-code-gen and @vue/component-compiler in /src/pretix/static/npm_dir (#4210)
Bumps [pug-code-gen](https://github.com/pugjs/pug) and [@vue/component-compiler](https://github.com/vuejs/vue-component-compiler). These dependencies needed to be updated together.

Updates `pug-code-gen` from 2.0.3 to 3.0.3
- [Release notes](https://github.com/pugjs/pug/releases)
- [Commits](https://github.com/pugjs/pug/compare/pug@2.0.3...pug-code-gen@3.0.3)

Updates `@vue/component-compiler` from 4.2.3 to 4.2.4
- [Release notes](https://github.com/vuejs/vue-component-compiler/releases)
- [Changelog](https://github.com/vuejs/vue-component-compiler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-component-compiler/compare/v4.2.3...v4.2.4)

---
updated-dependencies:
- dependency-name: pug-code-gen
  dependency-type: indirect
- dependency-name: "@vue/component-compiler"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 14:48:55 +02:00
Raphael Michel
b939fad1c0 Sendmail: Prevent confusion around setting attach_tickets (Z#23155893) (#4211) 2024-06-10 14:48:47 +02:00
dependabot[bot]
fb3a608c54 Update django-hijack requirement from ==3.4.* to ==3.5.* (#4198)
Updates the requirements on [django-hijack](https://github.com/django-hijack/django-hijack) to permit the latest version.
- [Release notes](https://github.com/django-hijack/django-hijack/releases)
- [Changelog](https://github.com/django-hijack/django-hijack/blob/master/docs/release-button.png)
- [Commits](https://github.com/django-hijack/django-hijack/compare/3.4.0...3.5.0)

---
updated-dependencies:
- dependency-name: django-hijack
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 14:31:17 +02:00
Raphael Michel
ebda10542e Add IE11 banner to frontend (#4207) 2024-06-10 14:29:17 +02:00
dependabot[bot]
93dd6bf34d Bump @babel/preset-env from 7.24.5 to 7.24.6 in /src/pretix/static/npm_dir (#4189)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.5 to 7.24.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 14:12:02 +02:00
David Vaz
52148ebb7a Translations: Update Portuguese (Portugal)
Currently translated at 56.3% (129 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/pt_PT/

powered by weblate
2024-06-10 14:11:41 +02:00
David Vaz
82b4fe2733 Translations: Update Portuguese (Portugal)
Currently translated at 88.0% (4962 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pt_PT/

powered by weblate
2024-06-10 14:11:41 +02:00
alemairebe
79750e4f4b Translations: Update French
Currently translated at 96.2% (5423 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-06-10 14:11:41 +02:00
Mira
dbabbf7aab Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-10 14:11:41 +02:00
Mira
6158a1f2a4 Translations: Update German
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-10 14:11:41 +02:00
Charlie Lundberg
68f6f921b5 Translations: Update Swedish
Currently translated at 20.7% (1171 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-10 14:11:41 +02:00
Charlie Lundberg
d0e672435a Translations: Update Swedish
Currently translated at 20.6% (1163 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-10 14:11:41 +02:00
Raphael Michel
5bc622bcfe PayPal: Validate proper payee set with ISU integration (#4206) 2024-06-10 14:10:02 +02:00
Raphael Michel
d0184c1f48 PayPal: Fix issue in ASV setup (PRETIXEU-A5V) 2024-06-10 12:28:57 +02:00
Raphael Michel
e28bbb7ea0 Voucher creation: Fix TypeError in validation (PRETIXEU-A52) 2024-06-10 12:23:20 +02:00
Raphael Michel
fe54a42fc7 Web checkin: Render special cases of pending state in search (Z#23154934) (#4193) 2024-06-04 21:53:30 +02:00
Raphael Michel
7365f165ad Thumbnails: Keep frame durations of GIFs (#4183) 2024-06-04 21:53:20 +02:00
Raphael Michel
90ce802a33 Item form: Prevent combining validity_mode with gift cards (#4187) 2024-06-04 11:57:49 +02:00
Raphael Michel
d463878514 Do not use price suggestion if voucher is used (Z#23155018) (#4195) 2024-06-04 11:57:26 +02:00
Charlie Lundberg
dd7ee84d29 Translations: Update Swedish
Currently translated at 20.2% (1143 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-03 12:48:45 +02:00
Jo Siebert
f1e2d1f44c Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-06-03 12:48:45 +02:00
Jo Siebert
87a6a58f32 Translations: Update German
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-06-03 12:48:45 +02:00
Luan Thien
b2dd56bd41 Translations: Update Vietnamese
Currently translated at 1.5% (90 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/vi/

powered by weblate
2024-06-03 12:48:45 +02:00
Charlie Lundberg
f0ceab2305 Translations: Update Swedish
Currently translated at 19.7% (1113 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-03 12:48:45 +02:00
danijossnet
14e3316dd9 Translations: Update Greek
Currently translated at 49.7% (2803 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/el/

powered by weblate
2024-06-03 12:48:45 +02:00
Luan Thien
eb28fdcba9 Translations: Update Vietnamese
Currently translated at 55.0% (126 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/vi/

powered by weblate
2024-06-03 12:48:45 +02:00
Luan Thien
49e4a0faa0 Translations: Update Vietnamese
Currently translated at 1.5% (89 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/vi/

powered by weblate
2024-06-03 12:48:45 +02:00
Nikolai
e486089590 Translations: Update Danish
Currently translated at 62.4% (143 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/da/

powered by weblate
2024-06-03 12:48:45 +02:00
Nikolai
4bb02d4ad9 Translations: Update Danish
Currently translated at 31.2% (1761 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-03 12:48:45 +02:00
Luan Thien
8ad852d9cb Translations: Update Vietnamese
Currently translated at 0.8% (46 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/vi/

powered by weblate
2024-06-03 12:48:45 +02:00
Nikolai
868fcfc471 Translations: Update Danish
Currently translated at 30.9% (1745 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-03 12:48:45 +02:00
Nikolai
d847c9a095 Translations: Update Danish
Currently translated at 30.9% (1744 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-06-03 12:48:45 +02:00
Charlie Lundberg
d1c6b22624 Translations: Update Swedish
Currently translated at 19.4% (1093 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-06-03 12:48:45 +02:00
mathbrito
842987f48e Translations: Update Portuguese (Brazil)
Currently translated at 11.7% (664 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pt_BR/

powered by weblate
2024-06-03 12:48:45 +02:00
Jannik
58fc13ed91 Docs: Fix metrics names (#4192) 2024-06-03 12:33:28 +02:00
Raphael Michel
8010d2e6bb Update GitLab CI script 2024-05-31 17:46:45 +02:00
Raphael Michel
1566f54764 VAT ID validation: Fix crash with invalid Norwegian IDs (PRETIXEU-A3J) 2024-05-29 09:31:58 +02:00
Richard Schreiber
9d380557e1 SEO improvements - add h1.sr-only if only header-image is used
* add hidden h1 with event-title if header-image only

* add event-title to alt-attribute of header-image

* add hidden setting for google_site_verification
2024-05-28 09:18:15 +02:00
Martin Gross
5758e0dd68 PPv2 APM: Create referenced PPObjects for APM Orders; enable webhooks to capture them (#3958) 2024-05-27 13:45:37 +02:00
Martin Gross
b4629e24a5 Downgrade requests to 2.31.* again while waiting for 2.33.3 release 2024-05-27 12:11:40 +02:00
Raphael Michel
27f5121211 Bump version to 2024.6.0.dev0 2024-05-24 14:11:21 +02:00
Raphael Michel
a5007e4bd6 Bump version to 2024.5.0. 2024-05-24 14:10:29 +02:00
Richard Schreiber
fb3046210b Harden timing when getting order with secret check (#4177) 2024-05-24 14:09:18 +02:00
Raphael Michel
37908bd042 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-05-24 11:04:49 +02:00
Raphael Michel
74bcbe8f07 Translations: Update German
Currently translated at 100.0% (5634 of 5634 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-05-24 11:04:49 +02:00
Raphael Michel
29f378c58b Update wordlists 2024-05-24 10:56:10 +02:00
Raphael Michel
9b537aeb5c Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-05-24 10:47:49 +02:00
Raphael Michel
4b5cd35a0e Add a "the" 2024-05-24 10:47:49 +02:00
dependabot[bot]
e0675233d5 Update protobuf requirement from ==5.26.* to ==5.27.* (#4174)
Updates the requirements on [protobuf](https://github.com/protocolbuffers/protobuf) to permit the latest version.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v5.26.0-rc1...v5.27.0)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 10:47:32 +02:00
Raphael Michel
e9726a5227 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-05-24 10:10:01 +02:00
Mira
78b65d0757 Document exhibitor_tags field in API docs (#4172)
* Document exhibitor_tags field in API

* Update doc/plugins/exhibitors.rst

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-05-24 10:00:44 +02:00
Serhii Horichenko
ef620ceb37 Translations: Update Ukrainian
Currently translated at 63.8% (3587 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-24 09:50:45 +02:00
Charlie Lundberg
8575a5f1cd Translations: Update Swedish
Currently translated at 19.0% (1070 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-05-24 09:50:45 +02:00
Sinan Sarıçınar
5762ffc035 Translations: Update Turkish
Currently translated at 44.3% (2494 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/tr/

powered by weblate
2024-05-24 09:50:45 +02:00
Raphael Michel
79286bb051 Translations: Update French
Currently translated at 96.4% (5424 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-05-24 09:50:45 +02:00
Mira
05a2f411db Improve order secret handling (#4139)
- use hmac.compare_digest for all secret comparisons
- use salted_hmac with sha256 instead of plain sha1 for hashed secrets
- move secret handling into helper functions
2024-05-23 14:30:16 +02:00
Raphael Michel
e93e5c047c Waiting list: Fix pathological performance on large series with seating (#4169) 2024-05-23 11:51:48 +02:00
Raphael Michel
2619a658c9 Widget: Allow passing more invoice data fields (#4162) 2024-05-23 11:19:59 +02:00
Raphael Michel
808775c76b Widget: Do not open seating plan when pressing return in input field (#4163) 2024-05-23 11:18:09 +02:00
Raphael Michel
9f297fbd25 Widget: Fix data-invoice-address-country being overridden by GeoIP (#4168) 2024-05-23 11:17:54 +02:00
Serhii Horichenko
d882da0adb Translations: Update Ukrainian
Currently translated at 63.6% (3577 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-23 11:17:02 +02:00
Serhii Horichenko
73bd4a746e Translations: Update Ukrainian
Currently translated at 98.2% (225 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/uk/

powered by weblate
2024-05-23 11:17:02 +02:00
Serhii Horichenko
bc5d0763f3 Translations: Update Ukrainian
Currently translated at 63.6% (3576 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-23 11:17:02 +02:00
Charlie Lundberg
ff084f04b1 Translations: Update Swedish
Currently translated at 19.0% (1069 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-05-23 11:17:02 +02:00
Richard Schreiber
71af40a08b Simplify merging rotated background PDFs (#4166)
* Simplify merging rotated background PDFs

* fix code style issues
2024-05-23 08:55:51 +02:00
Raphael Michel
ef60093bae Update pypdf requirement from ==3.9.* to ==4.2.* (#4159)
* Change PDF merging for compatibility with pypdf 4

* Update pypdf requirement from ==3.9.* to ==4.2.*

* fix pypdf API-changes

* fix missing removal of deepcopy

* fix rotated PDF-backgrounds

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-05-22 14:56:21 +02:00
Mira
49c4cc639f Fix time machine permission via pretix_event_access sessions for staff users (#4160) 2024-05-22 13:13:50 +02:00
Charlie Lundberg
e2800019f6 Translations: Update Swedish
Currently translated at 86.0% (197 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/sv/

powered by weblate
2024-05-22 09:15:52 +02:00
Charlie Lundberg
c44ea8aa81 Translations: Update Swedish
Currently translated at 18.2% (1026 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/sv/

powered by weblate
2024-05-22 09:15:52 +02:00
Serhii Horichenko
47a03e1b2a Translations: Update Ukrainian
Currently translated at 63.5% (3573 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-22 09:15:52 +02:00
Raphael Michel
86ddca15ca Keep Python 3.9 compatibility for now / Revert "Fix more Python 3.12 warnings"
This reverts commit 294b3966b0.
2024-05-22 09:02:25 +02:00
Raphael Michel
294b3966b0 Fix more Python 3.12 warnings 2024-05-21 14:40:41 +02:00
dependabot[bot]
fecc00231b Update requests requirement from ==2.31.* to ==2.32.* (#4155)
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 14:24:46 +02:00
dependabot[bot]
b3dfc459f5 Update pep8-naming requirement from ==0.13.* to ==0.14.* (#4152)
Updates the requirements on [pep8-naming](https://github.com/PyCQA/pep8-naming) to permit the latest version.
- [Release notes](https://github.com/PyCQA/pep8-naming/releases)
- [Changelog](https://github.com/PyCQA/pep8-naming/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/PyCQA/pep8-naming/compare/0.13.0...0.14.1)

---
updated-dependencies:
- dependency-name: pep8-naming
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 14:24:25 +02:00
Krisztián Henrik Papp
e21d63a7be Translations: Update Hungarian
Currently translated at 2.0% (115 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/hu/

powered by weblate
2024-05-21 14:23:50 +02:00
Mira
9a807df158 Fix pretix_event_access (custom domain) sessions for staff users (#4158) 2024-05-21 13:26:12 +02:00
Raphael Michel
e95d551711 Silence deprecation warnings on Python 3.12 2024-05-21 12:59:58 +02:00
Raphael Michel
7188e44fe5 Stripe: Add support for Swish (#4149)
* Stripe: Add support for Swish

* Update src/pretix/plugins/stripe/payment.py

Co-authored-by: Martin Gross <gross@rami.io>

---------

Co-authored-by: Martin Gross <gross@rami.io>
2024-05-17 13:33:03 +02:00
Richard Schreiber
a6a93555b6 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5621 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-05-17 11:53:57 +02:00
Richard Schreiber
94eb473e42 Translations: Update German
Currently translated at 100.0% (5621 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-05-17 11:53:57 +02:00
Serhii Horichenko
cbc3a344c1 Translations: Update Ukrainian
Currently translated at 98.2% (225 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/uk/

powered by weblate
2024-05-17 11:53:57 +02:00
Serhii Horichenko
47db52d75f Translations: Update Ukrainian
Currently translated at 63.3% (3559 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-17 11:53:57 +02:00
Mira
ba99fe597c Use correct condition for time machine check in template (#4151) 2024-05-17 11:29:54 +02:00
Mira
b638c00952 Time machine mode [Z#23129725] (#3961)
Allows organizers to test their shop as if it were a different date and time.

Implemented using a time_machine_now() function which is used instead of regular now(), which can overlay the real date time with a value from a ContextVar, assigned from a session value in EventMiddleware.

For more information, see doc/development/implementation/timemachine.rst

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: Raphael Michel <michel@rami.io>
2024-05-17 10:52:17 +02:00
Raphael Michel
bfcca7046a Vouchers: Add copy button for URL 2024-05-16 11:57:50 +02:00
Raphael Michel
ad5d10ff67 Fix missing serializer class 2024-05-15 11:01:32 +02:00
Raphael Michel
54d327deea Badges: Fix name clash of cache property 2024-05-15 09:46:56 +02:00
Raphael Michel
d6505f946f API: Allow setting payment_giftcard__enabled 2024-05-14 15:45:42 +02:00
Raphael Michel
9c4efa7dcf Fix link on orders with memberships without customer (PRETIXEU-A1W) 2024-05-14 11:59:16 +02:00
Raphael Michel
e6d26c4962 Add comment on pypdf upgrade 2024-05-14 11:09:02 +02:00
Serhii Horichenko
7ddbbe21f7 Translations: Update Ukrainian
Currently translated at 62.8% (3534 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-14 11:04:24 +02:00
Serhii Horichenko
8d5ad0bd9e Translations: Update Russian
Currently translated at 19.5% (1101 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ru/

powered by weblate
2024-05-14 11:04:24 +02:00
Raphael Michel
aff6a6f022 Revert "Update pypdf requirement from ==3.9.* to ==4.2.* (#4145)"
This reverts commit 46008818ce.
2024-05-14 10:59:43 +02:00
dependabot[bot]
46008818ce Update pypdf requirement from ==3.9.* to ==4.2.* (#4145)
Updates the requirements on [pypdf](https://github.com/py-pdf/pypdf) to permit the latest version.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/3.9.0...4.2.0)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 09:33:26 +02:00
Raphael Michel
95db04bad2 Revert "Update pypdf requirement from ==3.9.* to ==4.2.* (#4055)"
This reverts commit 46b2214836.
2024-05-13 18:29:41 +02:00
Serhii Horichenko
d0c62ec1cf Translations: Update Ukrainian
Currently translated at 62.8% (3532 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-13 10:06:04 +02:00
Serhii Horichenko
d6cbb130bd Translations: Update Ukrainian
Currently translated at 62.8% (3532 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-13 10:06:04 +02:00
Martin Gross
097d2fcda0 Translations: Update Norwegian Bokmål
Currently translated at 97.0% (5455 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nb_NO/

powered by weblate
2024-05-13 10:06:04 +02:00
Ryo
41a7c13970 Translations: Update Japanese
Currently translated at 3.4% (194 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2024-05-13 10:06:04 +02:00
Raphael Michel
1b725810dd Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5621 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-05-08 17:54:00 +02:00
Raphael Michel
251f486480 Translations: Update German
Currently translated at 100.0% (5621 of 5621 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-05-08 17:54:00 +02:00
Adam Kaput
a7afcdf753 Translations: Update Polish
Currently translated at 40.0% (2243 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-05-08 17:54:00 +02:00
Nikolai
0722341073 Translations: Update Danish
Currently translated at 31.1% (1744 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-05-08 17:54:00 +02:00
Raphael Michel
207bf101b8 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-05-08 15:19:10 +02:00
Raphael Michel
e8f7cea1bf Allow attendees to modify their data (Z#23152886) (#4138)
* Allow attendees to modify their data

* Allow attendees to change ticket information

* Update src/pretix/control/templates/pretixcontrol/event/settings.html

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/presale/views/order.py

Co-authored-by: Mira <weller@rami.io>

* Update src/pretix/base/services/placeholders.py

Co-authored-by: Mira <weller@rami.io>

* Tests fix

* Fix test

---------

Co-authored-by: Mira <weller@rami.io>
2024-05-08 15:18:33 +02:00
Raphael Michel
aa55eb2de2 Reactivate order: Fix incorrect signal being sent 2024-05-08 09:56:37 +02:00
Mira
9dc5c1b266 Prevent transferring files from priv/ to pub/ on event clone (#3956)
* Prevent transferring files from priv/ to pub/ on event clone

* Also detect file names with node prefix

* Only transfer files in explicitly declared file fields

* Update django-hierarkey

* Add note to documentation about the new behaviour
2024-05-08 09:33:23 +02:00
Shintaro Okamatsu
514f1def4d Translations: Update Japanese
Currently translated at 3.4% (193 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2024-05-08 09:32:48 +02:00
AbdelatifAitBara
c2bc97a0d8 Translations: Update Arabic
Currently translated at 66.4% (3728 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ar/

powered by weblate
2024-05-08 09:32:48 +02:00
Serhii Horichenko
7fba473426 Translations: Update Ukrainian
Currently translated at 98.2% (225 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/uk/

powered by weblate
2024-05-08 09:32:48 +02:00
Serhii Horichenko
be87ba0000 Translations: Update Ukrainian
Currently translated at 62.9% (3531 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-08 09:32:48 +02:00
Adam Kaput
76b7643c39 Translations: Update Polish
Currently translated at 94.7% (217 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/pl/

powered by weblate
2024-05-08 09:32:48 +02:00
Adam Kaput
b1a3963b33 Translations: Update Polish
Currently translated at 39.7% (2226 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2024-05-08 09:32:48 +02:00
Raphael Michel
586e694ff3 Order import: Add expires column (Z#23152985) (#4137) 2024-05-08 09:09:55 +02:00
dependabot[bot]
f4383c67a4 Update fakeredis requirement from ==2.22.* to ==2.23.* (#4140)
Updates the requirements on [fakeredis](https://github.com/cunla/fakeredis-py) to permit the latest version.
- [Release notes](https://github.com/cunla/fakeredis-py/releases)
- [Commits](https://github.com/cunla/fakeredis-py/compare/v2.22.0...v2.23.0)

---
updated-dependencies:
- dependency-name: fakeredis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-08 09:07:51 +02:00
dependabot[bot]
46b2214836 Update pypdf requirement from ==3.9.* to ==4.2.* (#4055)
Updates the requirements on [pypdf](https://github.com/py-pdf/pypdf) to permit the latest version.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/3.9.0...4.2.0)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 14:32:48 +02:00
Raphael Michel
0e20d897d2 Prevent parallel refunds for the same order (Z#23152965) (#4136) 2024-05-07 14:32:02 +02:00
Raphael Michel
0c09cccd4f Docs: Add docker compose guide 2024-05-07 13:55:52 +02:00
Raphael Michel
5ca0833db1 Vouchers: Fix validation of quota when copying a blocking voucher (Z#23152799) (#4133)
* Vouchers: Fix validation of quota when copying a blocking voucher

* Bugfixes
2024-05-07 09:50:16 +02:00
Raphael Michel
7a63498333 PDF editor: Add variables for purchase date (Z#23152887) (#4134)
* PDF editor: Add variables for purchase date (Z#23152887)

* Fix order and add time
2024-05-07 09:48:05 +02:00
Raphael Michel
b8c0887f79 Widget: Fix CORS for cached JS 2024-05-07 09:31:56 +02:00
Raphael Michel
9da65f60d7 Voucher import: Fix validation quirks 2024-05-03 16:06:40 +02:00
Raphael Michel
806124304a Voucher get code validation 2024-05-03 14:34:51 +02:00
Serhii Horichenko
0d57673a47 Translations: Update Ukrainian
Currently translated at 62.9% (3529 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-03 09:52:42 +02:00
Raphael Michel
166b5e4f3b Change default password hash to argon2id (#4121)
* Change default password hash to argon2id

* Install argon2
2024-05-02 18:22:02 +02:00
Mira
541b8f5bd6 Discounts: Fix edge case in computation (#4126)
* Add new test case for discounts:

Two discounts:
- "For every 1 item1, you get three item2 for 10 % off."
- "For every 1 item1, you get five item3 for 10 % off."
Cart: 2x item1, 2x item2, 6x item3
Expected result: 2x item1 full price, 2x item2 discounted, 5x item3 discounted, 1x item3 full price

* Fix discount calculation bug

* Update src/pretix/base/models/discount.py

Co-authored-by: Raphael Michel <michel@rami.io>

* Update src/pretix/base/models/discount.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Raphael Michel <michel@rami.io>
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-05-02 18:21:56 +02:00
dependabot[bot]
d2b96b2425 Bump @babel/core from 7.24.3 to 7.24.5 in /src/pretix/static/npm_dir (#4125)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.24.3 to 7.24.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 18:21:30 +02:00
dependabot[bot]
04d4c4f8f1 Bump @babel/preset-env from 7.24.3 to 7.24.5 in /src/pretix/static/npm_dir (#4124)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.3 to 7.24.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.5/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 16:31:55 +02:00
Raphaël Deux
f4da94cbcd Translations: Update French
Currently translated at 96.7% (5424 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2024-05-02 16:31:45 +02:00
Serhii Horichenko
97e3d5387f Translations: Update Ukrainian
Currently translated at 98.2% (225 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/uk/

powered by weblate
2024-05-02 16:31:45 +02:00
Serhii Horichenko
8fc07523a9 Translations: Update Ukrainian
Currently translated at 62.8% (3526 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-05-02 16:31:45 +02:00
Nikolai
f18b0ae187 Translations: Update Danish
Currently translated at 31.1% (1744 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-05-02 16:31:45 +02:00
Raphael Michel
f7e16f56ac Revert "Install argon2"
This reverts commit 3f4e869cea.
2024-05-02 16:27:46 +02:00
Raphael Michel
3f4e869cea Install argon2 2024-05-02 16:27:37 +02:00
Martin Gross
8c2a1d58f4 Templates: Add Herma 4515 (Acetatesilk) to repository 2024-05-02 13:57:46 +02:00
Raphael Michel
0b05eb34f4 Fix style of buttons in alerts 2024-04-30 12:44:41 +02:00
Raphael Michel
be48c5f94c Bump version to 2024.5.0.dev0 2024-04-30 11:11:13 +02:00
Raphael Michel
cebb6d3b43 Introduce locking to prevent duplicate invoices (Z#23150548) (#4067)
* Introduce locking to prevent duplicate invoices

This is not a perfect solution as it does not handle all code paths to
create invoices, but it handles all that seem likely to be triggered
concurrently

* Review note
2024-04-30 10:43:13 +02:00
Richard Schreiber
0de96ed066 Add links to invalid inputs on error alert (Z#23149061) (#4114)
* Add links to invalid inputs on error alert

* add errors in sub-forms to message, fix issues with multi-checkboxes labels and inputs

* add scrollTarget.scrollIntoView

* add missing semi-colon

* improve comment

* add style for links in alert-danger

* fix link color for all alert-boxes

* Update src/pretix/static/pretixcontrol/js/ui/main.js

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-04-30 10:18:32 +02:00
dependabot[bot]
a9d506b1fa Update pytest-xdist requirement from ==3.5.* to ==3.6.* (#4118)
Updates the requirements on [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest-xdist/releases)
- [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.5.0...v3.6.1)

---
updated-dependencies:
- dependency-name: pytest-xdist
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-30 10:14:54 +02:00
Serhii Horichenko
7a01057429 Translations: Update Ukrainian
Currently translated at 89.9% (206 of 229 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/uk/

powered by weblate
2024-04-30 10:14:00 +02:00
Serhii Horichenko
64e1a602d6 Translations: Update Ukrainian
Currently translated at 62.9% (3527 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/uk/

powered by weblate
2024-04-30 10:14:00 +02:00
Nikolai
fe060c387a Translations: Update Danish
Currently translated at 31.0% (1741 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-04-30 10:14:00 +02:00
dependabot[bot]
1dba4c7cc9 Update pytest requirement from ==8.1.* to ==8.2.* (#4119)
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.0.dev0...8.2.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-29 21:02:07 +02:00
Richard Schreiber
20b2a3d2aa Control: add link to orders for each subevent in list of subevents (Z#23129436) (#3566) 2024-04-29 18:44:42 +02:00
Raphael Michel
044f0c5480 Fix N+1 query in event calendar found by sentry (#4104)
* Fix N+1 query in event calendar found by sentry

* isort

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-04-29 18:41:50 +02:00
Raphael Michel
4d394f9e8a Answer file export: Allow to filter by subevent (Z#23150581) (#4066)
* Answer file export: Allow to filter by subevent (Z#23150581)

* Update src/pretix/base/exporters/answers.py

Co-authored-by: Mira <weller@rami.io>

* Fix isort

---------

Co-authored-by: Mira <weller@rami.io>
2024-04-29 18:12:58 +02:00
Raphael Michel
247c4c6c9c Do not remove unavailable addons when changing order (Z#23150855) (#4086) 2024-04-29 18:11:20 +02:00
Raphael Michel
11a038feb3 Allow secret generators to access order datetime (#4110) 2024-04-26 15:09:01 +02:00
Raphael Michel
9d57ea8534 API: Do not write log entry for events when no changes are made (#4090) 2024-04-26 13:56:46 +02:00
Raphael Michel
189c77207f Bump version to 2024.4.0 2024-04-26 13:53:49 +02:00
Raphael Michel
3422003a9c Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5607 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-26 13:53:17 +02:00
Raphael Michel
8da38ba99d Translations: Update German
Currently translated at 100.0% (5607 of 5607 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-26 13:53:17 +02:00
Raphael Michel
fc05208b92 Docs: Add note on Swissbit TSE to Android support policy 2024-04-26 13:36:49 +02:00
Raphael Michel
b163109c56 Docs: ADd undocumented metrics 2024-04-26 12:28:38 +02:00
Raphael Michel
3ba818336e Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-04-26 11:26:25 +02:00
Raphael Michel
8aecf4f98f Voucher import: Validate code not empty 2024-04-26 11:25:49 +02:00
Martin Gross
42f3ca9661 SecHelper: Fix typo in logging statement 2024-04-24 18:13:27 +02:00
Raphael Michel
f7b405b210 Voucher import: Do not allow to keep min/max usages empty 2024-04-24 14:20:54 +02:00
Raphael Michel
11a6390cfc Voucher import: Fix quota name check 2024-04-24 10:28:10 +02:00
dependabot[bot]
239a7746df Update djangorestframework requirement from ==3.14.* to ==3.15.* (#4001)
Updates the requirements on [djangorestframework](https://github.com/encode/django-rest-framework) to permit the latest version.
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.14.0...3.15.0)

---
updated-dependencies:
- dependency-name: djangorestframework
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raphael Michel <michel@rami.io>
2024-04-23 16:56:02 +02:00
Wikinaut
03701eaa82 Docs: Add explicit user change to installation guide (#3972)
* Update manual_smallscale.rst

(I propose to) 
add

- sudo su pretix ; and
- deactivate

commands to the documentation,n

* Update doc/admin/installation/manual_smallscale.rst

* Update doc/admin/installation/manual_smallscale.rst

* Update doc/admin/installation/manual_smallscale.rst

---------

Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
2024-04-23 15:18:33 +02:00
dependabot[bot]
356f215d8e Update celery requirement from ==5.3.* to ==5.4.* (#4091)
Updates the requirements on [celery](https://github.com/celery/celery) to permit the latest version.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.3.0a1...v5.4.0)

---
updated-dependencies:
- dependency-name: celery
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 15:11:40 +02:00
dependabot[bot]
7962c4e380 Update django-otp requirement from ==1.4.* to ==1.5.* (#4083)
Updates the requirements on [django-otp](https://github.com/django-otp/django-otp) to permit the latest version.
- [Changelog](https://github.com/django-otp/django-otp/blob/master/CHANGES.rst)
- [Commits](https://github.com/django-otp/django-otp/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: django-otp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 15:11:31 +02:00
dependabot[bot]
a59711ed32 Update django-statici18n requirement from ==2.4.* to ==2.5.* (#4106)
Updates the requirements on [django-statici18n](https://github.com/zyegfryed/django-statici18n) to permit the latest version.
- [Changelog](https://github.com/zyegfryed/django-statici18n/blob/main/docs/changelog.rst)
- [Commits](https://github.com/zyegfryed/django-statici18n/compare/v2.4.0...v2.5.0)

---
updated-dependencies:
- dependency-name: django-statici18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 15:11:18 +02:00
dependabot[bot]
49370a5e08 Update reportlab requirement from ==4.1.* to ==4.2.* (#4092)
Updates the requirements on [reportlab](https://www.reportlab.com/) to permit the latest version.

---
updated-dependencies:
- dependency-name: reportlab
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 15:03:54 +02:00
dependabot[bot]
980aec7326 Update fakeredis requirement from ==2.21.* to ==2.22.* (#4105)
Updates the requirements on [fakeredis](https://github.com/cunla/fakeredis-py) to permit the latest version.
- [Release notes](https://github.com/cunla/fakeredis-py/releases)
- [Commits](https://github.com/cunla/fakeredis-py/compare/v2.21.0...v2.22.0)

---
updated-dependencies:
- dependency-name: fakeredis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 15:03:09 +02:00
Raphael Michel
44294110fe Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5606 of 5606 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-23 14:59:03 +02:00
Raphael Michel
ce1078a783 Translations: Update German
Currently translated at 100.0% (5606 of 5606 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-23 14:59:03 +02:00
Raphael Michel
0e0cede0ee Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-04-23 14:41:20 +02:00
Martin Gross
5c833cd493 Add special input widgets for markdown fields (#1577)
* Add markdown text input widgets

* Update src/pretix/static/pretixcontrol/scss/_forms.scss

* Improvements

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-04-23 14:40:30 +02:00
Raphael Michel
64d6a34039 Ensure correct language of invoice attachment file name (Z#23150936) (#4094) 2024-04-23 14:07:30 +02:00
Mira
cf380069b4 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5598 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-23 14:07:17 +02:00
Mira
48168a4c68 Translations: Update German
Currently translated at 100.0% (5598 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-23 14:07:17 +02:00
Raphael Michel
6482fe79b0 Add force to log entry in extend_order() 2024-04-22 21:34:46 +02:00
Raphael Michel
0f696f42f6 Do not allow currency codes that to not represent money (#4056)
* Do not allow currency codes that to not represent money

* Rebase migration

* Fix blacklist
2024-04-22 16:22:30 +02:00
Martin Gross
79d59553d7 POS: Do not fail when rendering ZVT-transactions without a cardName or cardType 2024-04-22 13:52:18 +02:00
Raphael Michel
cc903c39f0 Docs: Fix copy-paste error in COEP docs 2024-04-22 13:18:34 +02:00
Raphael Michel
b6a42ac8d2 Widget: Document and improve situation around COEP (Z#23149909) (#4051) 2024-04-22 13:15:33 +02:00
Raphael Michel
5f5001edb5 File upload: Fix thumbnailing of current image (Z#23151293) (#4098) 2024-04-22 13:14:28 +02:00
Raphael Michel
fb403dad88 Add comment field to subevents (Z#23148472) (#4099)
* Add comment field to subevents (Z#23148472)

* Review fix
2024-04-22 12:56:29 +02:00
Christiaan de Die le Clercq
a73c8f580d Translations: Update Dutch
Currently translated at 88.1% (4937 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-04-22 11:38:27 +02:00
Raphael Michel
f490c89e98 Seating plans: Do not allow GUIDs starting or ending with spaces (#4093) 2024-04-22 11:31:34 +02:00
Raphael Michel
159658ae46 Fix typo in attribute name 2024-04-19 17:34:38 +02:00
Christiaan de Die le Clercq
595aff0579 Add a community install guide page (#4096) 2024-04-19 15:08:47 +02:00
Raphael Michel
b2842ec3a0 Checkin: Allow to use presence state in rules (#4061) 2024-04-18 13:15:31 +02:00
Raphael Michel
f09f07ec7c Add Android Version Support Policy (#4074) 2024-04-18 11:35:28 +02:00
Richard Schreiber
cff073f0d6 Fix: show human-readable country name in profile description for custom country-code questions (#4078) 2024-04-18 11:08:21 +02:00
dependabot[bot]
eb9d0c6cf9 Update sphinx requirement from ==7.2.* to ==7.3.* (#4088)
Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx) to permit the latest version.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.2.0...v7.3.5)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-18 11:06:52 +02:00
dependabot[bot]
e263946c3f Update django-bootstrap3 requirement from ==23.6.* to ==24.2 (#4087)
Updates the requirements on [django-bootstrap3](https://github.com/zostera/django-bootstrap3) to permit the latest version.
- [Changelog](https://github.com/zostera/django-bootstrap3/blob/main/CHANGELOG.md)
- [Commits](https://github.com/zostera/django-bootstrap3/compare/v23.6...v24.2)

---
updated-dependencies:
- dependency-name: django-bootstrap3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-18 11:06:46 +02:00
Shiiko
7ee957cff0 Translations: Update Chinese (Simplified)
Currently translated at 52.5% (2940 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/zh_Hans/

powered by weblate
2024-04-17 17:18:31 +02:00
Raphael Michel
ac2fe4b62d Fix crash in placeholder samples (PRETIXEU-9YP) 2024-04-17 16:37:40 +02:00
Raphael Michel
577e276df3 Fix voucher import validation issue (PRETIXEU-9YF) 2024-04-17 15:42:05 +02:00
Richard Schreiber
11956a8f4d fix isort 2024-04-15 16:25:25 +02:00
Raphael Michel
d0c58713c4 Badge/ticket export: Allow to sort by company 2024-04-15 10:55:40 +02:00
Raphael Michel
46da0bda61 Placeholders: Use dynamic sample for name_for_salutation 2024-04-15 10:55:40 +02:00
Raphael Michel
009e3a6d36 Respect Order.valid_if_pending for mail_attach_ical_paid_only (#4065) 2024-04-12 15:00:00 +02:00
Martin Gross
c01855270b Approval Process: Attach ical to approval-messages if properly configured (#4064) 2024-04-12 11:18:21 +02:00
dependabot[bot]
2df1585b71 Update sentry-sdk requirement from ==1.44.* to ==1.45.* (#4058)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.44.0...1.45.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-11 13:33:01 +02:00
Raphael Michel
bf48ae567f NREI export: Fix parsing of stripe data 2024-04-11 09:27:55 +02:00
dependabot[bot]
5a72c72d18 Update django-otp requirement from ==1.3.* to ==1.4.* (#4057)
Updates the requirements on [django-otp](https://github.com/django-otp/django-otp) to permit the latest version.
- [Changelog](https://github.com/django-otp/django-otp/blob/master/CHANGES.rst)
- [Commits](https://github.com/django-otp/django-otp/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: django-otp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 09:56:40 +02:00
Raphael Michel
ac02f3b417 API: Fix crash in order creation (PRETIXEU-9XS) 2024-04-10 09:40:35 +02:00
Martin Gross
58add74b3a Stripe: Add PayPal (#4049) (Z#23123667) 2024-04-09 10:06:58 +02:00
Raphael Michel
0067c3537d Fix invalid orders being created in a complex situation (#4054)
This was a bug that took days to find. The story goes like this: A cart
is created with four positions that each include four bundled positions.
A discount is applied, changing the price of *one* of the four top-level
positions to a reduced value. The list of position IDs gets passed to
`perform_order()`, which later passes it on to `transform_cart_positions()`.
`transform_cart_positions()`, however, receives the positions in an order
that has the first-level product *after* the bundled products that
belong to it. Therefore, it can't properly assign the parent-child
relationship between the positions.

The main reason is that cart positions are processed in "database order"
in a number of places, i.e. we make `SELECT` queries without an explicit
`ORDER BY` statement, leading the database to respond in unspecified
order. This is the case for `get_cart()` and hence for `CartMixin.positions`,
and hence for the list of position IDs that is passed to `perform_order()`
and hence for the order in which discounts are processed.

Therefore, if this "databse order" of the cart positions changes, the
discount compuation in `_check_positions()` might make a different choice
of *which* cart position should receive the discount than the CartManager
originally did. That's not nice, but most customers would not even
notice that a different one of their four (otherwise identical) tickets
is now discounted than the cart originally showed.

This leads to `_check_positions()` changing the price on two of the
cart positions. However, it only changes the price on the copy of
the CartPosition object that is directly part of the positions array,
while the `addon_to` attribute of its bundled positions contain a
*different* representation of the same cart position, that is not
refreshed to have the updated price now in the database.

This causes the `CartPosition.sort_key` of the bundled products to be
significantly different from the one of their parent products, which can
cause `transform_cart_positions()` to try to insert them before their
respective parent product, which is how the bug leads to the nasty end
result.

Now, I'm still not sure why this has happened *now* for the first time,
but I suspect it *might* even have something to do with our operations
team tuning our autovacuum parameters on our production installation,
which might make it *more likely* that newly created cart positions are
arbitrarily  stored on PostgreSQL disk pages in a different order than
they were inserted than before.

This commit now fixes the bug now in two ways, each of which would be
sufficient to fix it for now, but together they make it hopefully more
stable in the future:

- `perform_order` no longer respects the order of the position IDs it
  gets passed in, but instead uses the order last displayed in the cart.
  Additionally, both `CartManager` and `_check_positions()` now sort
  positions by their `pk` value before applying discounts to ensure
  consistent choice of which position is discounted (using  `sort_key`
  here does not make much sense since it includes sorting by price,
  which is about to change).

- `_check_positions()` makes sure that after its completion, only one
  copy of the same `CartPosition` is in use that has the current price.

Additionally, this commit makes sure `sort_key` cache is cleared after
e.g. a price change.

It was hard to write a regression test, since "database order" is, by
definition, unreliable, but I tried my best.
2024-04-08 16:55:54 +02:00
Raphael Michel
64ae1d08a6 Docs: Fix incorrect API response 2024-04-05 17:28:44 +02:00
Raphael Michel
ca25c3c81e Add logging for special bug case (Z#23149646) 2024-04-04 18:13:54 +02:00
Raphael Michel
abbe9ec897 Order creation: Fail loudly on invalid addon-to relationship 2024-04-03 17:21:47 +02:00
Raphael Michel
a7735d5d9e API: Allow request_valid_from in the past (#4048) 2024-04-03 17:21:25 +02:00
Raphael Michel
174c81a22b Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5598 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-03 13:15:57 +02:00
Raphael Michel
38c6294ede Translations: Update German
Currently translated at 100.0% (5598 of 5598 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-03 13:15:57 +02:00
Raphael Michel
217ae90642 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-04-03 12:43:52 +02:00
Raphael Michel
0c998ca884 Remove special handling of translations in pretix/helpers 2024-04-03 12:43:20 +02:00
Raphael Michel
b1691f867d Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5594 of 5594 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-03 11:43:39 +02:00
Raphael Michel
72e451b27b Translations: Update German
Currently translated at 100.0% (5594 of 5594 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-03 11:43:39 +02:00
Raphael Michel
8124ced6c1 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-04-03 11:22:25 +02:00
Raphael Michel
a3139944f6 Send notifications about login with new client or country (#4032)
* Send notifications about login with new client or country

* Rebase migration

* Remove immediately

* Fix isort

* Text update
2024-04-03 11:19:20 +02:00
Felix Schäfer
48493c517b Add database.disable_server_side_cursors option (#4016) 2024-04-03 10:16:48 +02:00
dependabot[bot]
535a29bf4b Update css-inline requirement from ==0.13.* to ==0.14.* (#4043)
Updates the requirements on [css-inline](https://github.com/Stranger6667/css-inline) to permit the latest version.
- [Release notes](https://github.com/Stranger6667/css-inline/releases)
- [Changelog](https://github.com/Stranger6667/css-inline/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/css-inline/compare/c-v0.13.0...c-v0.14.0)

---
updated-dependencies:
- dependency-name: css-inline
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-03 10:16:13 +02:00
dependabot[bot]
9d415f5179 Update pillow requirement from ==10.2.* to ==10.3.* (#4044)
Updates the requirements on [pillow](https://github.com/python-pillow/Pillow) to permit the latest version.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-03 10:16:03 +02:00
Raphael Michel
990e9da21d Generalize import process from orders to more models (#4002)
* Generalize import process from orders to more models

* Add voucher import

* Model import: Guess assignments of based on column headers

* Fix lock_seats being pointless

* Update docs

* Update doc/development/api/import.rst

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/base/modelimport_vouchers.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-04-03 10:15:30 +02:00
Raphael Michel
4afb7a4976 Allow admins to generate emergency 2FA tokens (#4035)
* Allow admins to generate emergency 2FA tokens

* Update src/pretix/control/views/users.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-04-03 10:15:17 +02:00
Raphael Michel
22e5579ed1 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5585 of 5585 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-03 10:14:56 +02:00
Raphael Michel
79cd84e243 Translations: Update German
Currently translated at 100.0% (5585 of 5585 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-03 10:14:56 +02:00
Raphael Michel
fad4b8846c Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5585 of 5585 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-04-03 10:14:56 +02:00
Raphael Michel
0f4790afd8 Translations: Update German
Currently translated at 100.0% (5585 of 5585 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-04-03 10:14:56 +02:00
Raphael Michel
2068a5ac29 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-04-02 17:53:26 +02:00
Raphael Michel
440c97061c Fix duplicate key on SQLite (#4038)
* Fix duplicate key on SQLite

* Update migration
2024-04-02 17:37:37 +02:00
Raphael Michel
3b6d0c4341 Translations: Add Slovak 2024-04-02 17:28:11 +02:00
Raphael Michel
06ac4b0250 Translations: Add Slovak 2024-04-02 17:28:11 +02:00
Raphael Michel
a233b92f6f Add disable date of waiting list to event timeline (#4036) 2024-04-02 17:15:41 +02:00
Raphael Michel
4ea4189e6d Allow team admins to require two-factor authentication (#4034)
* Allow team admins to require two-factor authentication

* Add API tests

* Improve logic

* ADd button tooltip
2024-04-02 17:15:16 +02:00
Mira
50838b9cea Update github action versions (#4033) 2024-04-02 13:53:09 +02:00
Raphael Michel
c68ee56d51 Log discarding a valid session for suspicious reasons (#4025) 2024-04-02 13:52:30 +02:00
Thatthep
5c0587c30e Translations: Update Thai
Currently translated at 0.6% (36 of 5574 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/th/

powered by weblate
2024-04-02 11:45:11 +02:00
Raphael Michel
f3f42a8a42 Login: Add logging for incorrect JS hostnames 2024-04-02 11:34:43 +02:00
dependabot[bot]
20d0a9a0ed Update django-countries requirement from ==7.5.* to ==7.6.* (#4031)
Updates the requirements on [django-countries](https://github.com/SmileyChris/django-countries) to permit the latest version.
- [Changelog](https://github.com/SmileyChris/django-countries/blob/main/CHANGES.rst)
- [Commits](https://github.com/SmileyChris/django-countries/compare/v7.5...v7.6.1)

---
updated-dependencies:
- dependency-name: django-countries
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 11:07:51 +02:00
Raphael Michel
cda8144ff0 Enforce uniqueness of order codes and ticket secrets (#3988)
* Enforce uniqueness of order codes and ticket secrets

* Fix test cases which created orders with identical codes

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-04-02 11:07:40 +02:00
dependabot[bot]
43e8875c1e Update sentry-sdk requirement from ==1.42.* to ==1.44.* (#4021)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.42.0...1.44.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:26:37 +02:00
dependabot[bot]
28c142b2ed Update pytest-mock requirement from ==3.12.* to ==3.14.* (#4009)
Updates the requirements on [pytest-mock](https://github.com/pytest-dev/pytest-mock) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.12.0...v3.14.0)

---
updated-dependencies:
- dependency-name: pytest-mock
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:14:24 +02:00
dependabot[bot]
46203fd8ba Bump @babel/core from 7.24.0 to 7.24.3 in /src/pretix/static/npm_dir (#4027)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.24.0 to 7.24.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.3/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:13:39 +02:00
dependabot[bot]
52e45c37df Update webauthn requirement from ==2.0.* to ==2.1.* (#4022)
Updates the requirements on [webauthn](https://github.com/duo-labs/py_webauthn) to permit the latest version.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: webauthn
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:13:17 +02:00
dependabot[bot]
d1580dca2c Bump django-filter from 24.1 to 24.2 (#4017)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 24.1 to 24.2.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/24.1...24.2)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:13:00 +02:00
dependabot[bot]
cd9e672871 Bump pycparser from 2.21 to 2.22 (#4029)
Bumps [pycparser](https://github.com/eliben/pycparser) from 2.21 to 2.22.
- [Release notes](https://github.com/eliben/pycparser/releases)
- [Changelog](https://github.com/eliben/pycparser/blob/main/CHANGES)
- [Commits](https://github.com/eliben/pycparser/compare/release_v2.21...release_v2.22)

---
updated-dependencies:
- dependency-name: pycparser
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:10:42 +02:00
dependabot[bot]
427f508627 Bump @babel/preset-env from 7.24.0 to 7.24.3 in /src/pretix/static/npm_dir (#4028)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.0 to 7.24.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.3/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 10:10:01 +02:00
Raphael Michel
887d06a485 Add .watchmanconfig 2024-03-31 23:14:57 +02:00
Raphael Michel
fb49046ac1 Log and count user logins (#4020)
* Log and count user logins

* Allow metrics without label

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-03-28 17:18:51 +01:00
Martin Gross
ce826e50f7 PDF: Check for allowed font name before adding modifiers to the name 2024-03-27 12:54:35 +01:00
Raphael Michel
d866c6954d Bump to 2024.4.0.dev0 2024-03-27 12:15:31 +01:00
Raphael Michel
40c76dda74 Bump version to 2024.3.0 2024-03-27 12:14:07 +01:00
Raphael Michel
f532853021 Memberships: Prefer valid_from over event date for .is_valid() (#4003)
* Memberships: Prefer valid_from over event date for .is_valid()

* Fix tests

* Add parameter description

* Use reasonable default for requested_valid_from if membership starts in the future

* Set datetimepicker viewDate to closest allowed date

* Keep current value on going back to QuestionsStep

* Fix min_date/max_date in SplitDateTimePickerWidget

* Remove unused import

* Update src/pretix/base/models/memberships.py

Co-authored-by: Mira <weller@rami.io>

* Respect variations

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-03-27 12:11:20 +01:00
Martin Gross
8cb187502d Event Fonts: Only run register_event_fonts with actual, still existing events (FIXES PRETIXEU-9WE) 2024-03-26 17:13:13 +01:00
Raphael Michel
156037f2cd Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5574 of 5574 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-03-26 16:53:43 +01:00
Raphael Michel
134d63fb3f Translations: Update German
Currently translated at 100.0% (5574 of 5574 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-03-26 16:53:43 +01:00
Raphael Michel
816002fda0 Translations: Update German (informal) (de_Informal)
Currently translated at 99.9% (5572 of 5574 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-03-26 16:53:43 +01:00
Raphael Michel
3939bbc11c Translations: Update German
Currently translated at 100.0% (5574 of 5574 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-03-26 16:53:43 +01:00
Raphael Michel
95d1603cc7 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-03-26 14:37:18 +01:00
Raphael Michel
ada3ada699 Fix #3974 -- Webhooks: Add type of checkin (#3994) 2024-03-26 14:21:57 +01:00
Richard Schreiber
97eaeac4f2 Fix: improve order-change headline on customer’s order page (Z#23148804) (#4012) 2024-03-26 11:19:17 +01:00
Martin Gross
d67f5c650c Event-specific fonts and Web-Embedded Fonts (Z#23130701) (#3893) 2024-03-26 09:55:08 +01:00
Raphael Michel
273c1ae0a6 Waiting list: Allow to set auto-disable date (Z#23141338) (#4004)
* Waiting list: Allow to set auto-disable date (Z#23141338)

* ADd warning on non-esries events
2024-03-22 11:17:02 +01:00
Mira
a946c10ab4 Build jsi18n for all supported languages (#4007) 2024-03-22 10:19:27 +01:00
Raphael Michel
2d8fba7d7c Treat partially paid expired orders as overpaid orders (Z#23147757) (#3990)
* Treat partially paid expired orders as overpaid orders (Z#23147757)

* Use is_overpaid from annotate_overpayments in OrderFilterForm

* Revert change to pending sum

* Show warning on order page

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-03-22 10:17:51 +01:00
Mira
e4e0bd7ca0 Fix regression in thumb filter (#4006) 2024-03-21 14:32:01 +01:00
Richard Schreiber
3651c88289 Widget: pass utm-params from embedding page to presale 2024-03-20 09:19:02 +01:00
Richard Schreiber
c92ca40026 Fix code style/flake8 issue 2024-03-19 13:56:43 +01:00
Mira
4d00efb549 Fix generating thumbs for favicon.ico 2024-03-19 13:54:02 +01:00
Raphael Michel
7e60d13910 Fix #3984 -- API: Add phone to customer resource (#3992)
* Fix #3984 -- API: Add phone to customer resource

* add "phone": None to test

---------

Co-authored-by: Mira Weller <weller@rami.io>
2024-03-19 10:17:44 +01:00
Martin Weinelt
35800e21c7 Allow customization of cache and log directory (#3997)
On systems that follow the FHS it may be desirable to separate logs and
cache files into dedicated base directories (e.g. /var/log/pretix or
/var/cache/pretix).
2024-03-19 10:17:36 +01:00
Raphael Michel
99b4c5bd36 Fix cart grouping function to include membership and validity (#3991)
* Fix cart grouping function to include membership and validity

* Update src/pretix/presale/views/__init__.py

Co-authored-by: Mira <weller@rami.io>

---------

Co-authored-by: Mira <weller@rami.io>
2024-03-19 10:17:26 +01:00
Raphael Michel
f121205dd1 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (225 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2024-03-19 10:16:58 +01:00
Raphael Michel
1ac54cd209 Translations: Update German
Currently translated at 100.0% (225 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2024-03-19 10:16:58 +01:00
Raphael Michel
4694719a53 API: Fix creating free orders requiring approval 2024-03-19 10:10:57 +01:00
Raphael Michel
9513b6e8d7 Gift card payment: Fix public_name fallback 2024-03-15 17:09:21 +01:00
dependabot[bot]
4fd7d406a0 Update sentry-sdk requirement from ==1.41.* to ==1.42.* (#3983)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.41.0...1.42.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-15 16:49:52 +01:00
dependabot[bot]
47cb5b207a Update pytest-rerunfailures requirement from ==13.* to ==14.* (#3982)
Updates the requirements on [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) to permit the latest version.
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/13.0...14.0)

---
updated-dependencies:
- dependency-name: pytest-rerunfailures
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-15 16:42:03 +01:00
dependabot[bot]
7d2cf68727 Bump markdown from 3.5.2 to 3.6 (#3985)
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.5.2 to 3.6.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.5.2...3.6)

---
updated-dependencies:
- dependency-name: markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-15 16:41:49 +01:00
dependabot[bot]
459cb47ca8 Update protobuf requirement from ==4.25.* to ==5.26.* (#3986)
Updates the requirements on [protobuf](https://github.com/protocolbuffers/protobuf) to permit the latest version.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.25.0-rc1...v5.26.0)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-15 16:41:31 +01:00
Mira
39705556cd Fix tests that failed between 0:00 and 4:00 / 4:30 AM (#3987) 2024-03-15 16:40:56 +01:00
Raphael Michel
9f794290dc Memberships: Check valid_from/valid_until for parallel usage (#3975) 2024-03-15 16:40:41 +01:00
Raphael Michel
b6221ab6d9 Improve error messages for test mode checks for memberships 2024-03-15 15:57:11 +01:00
Richard Schreiber
483518bce9 Fix: left align first column header on invoices without tax 2024-03-15 13:34:19 +01:00
Raphael Michel
d9019ae735 Fix splitting free orders that require approval 2024-03-15 11:37:27 +01:00
Raphael Michel
721fd3b998 Remove incorrectly named, duplicate test file 2024-03-15 10:46:47 +01:00
Raphael Michel
ad0d3f5469 PDF editor: Minor UX adjustments 2024-03-14 12:34:21 +01:00
Raphael Michel
40b44f9272 Stripe: Do not open 3rd-party payment pages in iframe (#3981)
* Stripe: Do not open 3rd-party payment pages in iframe

* Update src/pretix/plugins/stripe/payment.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-03-14 11:49:41 +01:00
Mira
304d290f22 Presale: improve clientside handling of max-count for add-on products
* Fix typo in error message

* Use exclusive checkboxes for addon items with max_count == 1 and !multi_allowed

* combine exclusive items + variations

* move exclusive to containing fieldset

* fix add-on-exclusive

* add max_count check

* fix plus/minus-stepper buttons bubbling

* Update src/pretix/static/pretixpresale/js/ui/main.js

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-03-14 09:17:42 +01:00
Richard Schreiber
7592a8a575 Presale: add data-attribute price to each item’s article-element
* Presale: add data-attribute price to article

* fix price for items (defaul_price)

Co-authored-by: Mira <weller@rami.io>

* add data-price to voucher and addons, unlocalize price

* use universal display_price for items and variation, respect net or gross

---------

Co-authored-by: Mira <weller@rami.io>
2024-03-14 09:15:44 +01:00
dependabot[bot]
4f33159f93 Update sentry-sdk requirement from ==1.40.* to ==1.41.* (#3963)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.40.0...1.41.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 13:05:09 +01:00
dependabot[bot]
819ce6abf7 Bump django-filter from 23.5 to 24.1 (#3969)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 23.5 to 24.1.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/23.5...24.1)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 13:04:54 +01:00
dependabot[bot]
760dfd22b8 Bump @babel/core from 7.23.9 to 7.24.0 in /src/pretix/static/npm_dir (#3951)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.23.9 to 7.24.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 13:04:31 +01:00
Mira
f9eaa193c9 Add migration to force slash after hostname in returnurl prefixes (#3948)
* Add migration to force slash after hostname in returnurl prefixes

* isort

* add dependency to pretixbase
2024-03-12 12:41:48 +01:00
dependabot[bot]
c7720a2553 Update pytest requirement from ==8.0.* to ==8.1.* (#3976)
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.0rc1...8.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 12:41:33 +01:00
fyksen
7754f5420c Translations: Update Norwegian Bokmål
Currently translated at 98.1% (5462 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nb_NO/

powered by weblate
2024-03-12 12:41:21 +01:00
Raphael Michel
2c7ada6e86 OIDC: Do not expect uid to be string 2024-03-12 10:52:20 +01:00
dependabot[bot]
3f31843fd1 Update dnspython requirement from ==2.5.* to ==2.6.* (#3927)
Updates the requirements on [dnspython](https://github.com/rthalley/dnspython) to permit the latest version.
- [Release notes](https://github.com/rthalley/dnspython/releases)
- [Changelog](https://github.com/rthalley/dnspython/blob/main/doc/whatsnew.rst)
- [Commits](https://github.com/rthalley/dnspython/compare/v2.5.0rc1...v2.6.1)

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 13:19:11 +01:00
fyksen
952b9bd9b9 Translations: Update Norwegian Bokmål
Currently translated at 95.5% (215 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/nb_NO/

powered by weblate
2024-03-11 13:18:45 +01:00
fyksen
3619a6bcd0 Translations: Update Norwegian Bokmål
Currently translated at 98.1% (5462 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nb_NO/

powered by weblate
2024-03-11 13:18:45 +01:00
Richard Schreiber
3e2c12cdb0 Presale: fix auto-unchecked button-checkboxes (#3968) 2024-03-08 19:33:06 +01:00
Raphael Michel
a3ce3b9af3 Select2: Fix multi-select styling for events 2024-03-08 10:09:11 +01:00
Raphael Michel
b6461e9303 Select2: Set closeOnSelect for event selection 2024-03-08 10:08:44 +01:00
Raphael Michel
f7dfd51c2c Open invoices on new page 2024-03-07 10:57:41 +01:00
dependabot[bot]
3b98d87a26 Update python-dateutil requirement from ==2.8.* to ==2.9.* (#3950)
Updates the requirements on [python-dateutil](https://github.com/dateutil/dateutil) to permit the latest version.
- [Release notes](https://github.com/dateutil/dateutil/releases)
- [Changelog](https://github.com/dateutil/dateutil/blob/master/NEWS)
- [Commits](https://github.com/dateutil/dateutil/compare/2.8.0...2.9.0)

---
updated-dependencies:
- dependency-name: python-dateutil
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 12:21:12 +01:00
dependabot[bot]
f045062055 Bump @babel/preset-env from 7.23.9 to 7.24.0 in /src/pretix/static/npm_dir (#3952)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.23.9 to 7.24.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 12:17:23 +01:00
Felix Schäfer
eb501dd1ea Correct config key in docs (#3955) 2024-03-05 12:17:17 +01:00
Dean Wyns
2d8793c355 Translations: Update Dutch
Currently translated at 88.7% (4938 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-03-05 12:16:58 +01:00
Raphael Michel
d32bd717b7 Fix meta filter being selectable for export 2024-03-04 15:52:45 +01:00
Mira
6e6b75d55e Don't double file extension in clean_filename (#3942)
* Don't double file extension in clean_filename

* Don't use display_name as ClearableBasenameFileInput.FakeFile.name

Reason: it's used as the thumbnail source and therefore needs to be a valid file name and not some display name
2024-03-01 09:58:17 +01:00
Richard Schreiber
50b5f760bb Presale: prefer event’s microdata from settings over generated microdata (#3943) 2024-03-01 09:56:55 +01:00
Richard Schreiber
9ab2e61c31 Widget: fix quantity cut-off on very narrow screens (Z#23141650) (#3944)
* Widget: fix quantity cut-off on very narrow screens

* align price to left

* fix columns on mobile screens (missing clearfix)

* use min-width instead
2024-03-01 09:56:48 +01:00
Mira
4876a0b61f Allow multiple returnurl prefixes (Z#23145768) (#3941)
* Allow multiple returnurl prefixes, improve validation and docs.

* Fix typo

* Allow URL prefixes starting with http://localhost

* Add more explanation
2024-03-01 09:56:22 +01:00
Dean Wyns
56bbcb65c3 Translations: Update Dutch
Currently translated at 85.1% (4741 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-03-01 09:56:00 +01:00
Dean Wyns
5bb1cb498f Translations: Update Dutch
Currently translated at 83.9% (4672 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-03-01 09:56:00 +01:00
Raphael Michel
6bf23b0fdd Allow to create blocking vouchers for items with unspecified variation (#3932) 2024-02-29 16:45:41 +01:00
Raphael Michel
5deb1a8c69 Fix organizer being integer in mail_send_task 2024-02-29 08:59:15 +01:00
Raphael Michel
1523137300 Docs: Add extension of exhibitor API 2024-02-28 16:11:50 +01:00
Raphael Michel
04ef097eb1 Fix #65 -- Disallow None value for product default prices (#3847)
* Fix #65 -- Disallow None value for product default prices

* Fix #65 -- Disallow None value for product default prices

* Rebase migration
2024-02-28 16:10:53 +01:00
Raphael Michel
a5d4434a64 Bump to 2024.3.0.dev0 2024-02-28 14:40:30 +01:00
Raphael Michel
3b3c668153 Bump version to 2024.2.0 2024-02-28 14:38:56 +01:00
Raphael Michel
d339d67111 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5565 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-02-28 14:36:00 +01:00
Raphael Michel
a8aee6c824 Translations: Update German
Currently translated at 100.0% (5565 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-02-28 14:36:00 +01:00
Raphael Michel
6466987493 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5565 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-02-28 14:36:00 +01:00
Raphael Michel
ff962805cd Translations: Update German
Currently translated at 100.0% (5565 of 5565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-02-28 14:36:00 +01:00
Raphael Michel
2b5f46164f Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-02-28 14:11:42 +01:00
Adriano Lima
d74451ded1 Translations: Update Portuguese (Brazil)
Currently translated at 11.7% (656 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pt_BR/

powered by weblate
2024-02-28 14:10:55 +01:00
Raphael Michel
62f0c82d8d Order data export: Add event name 2024-02-28 12:16:49 +01:00
Raphael Michel
5b587774bb Fix context processors on error pages 2024-02-28 11:39:48 +01:00
Martin Gross
88ea8ee2ea Invoice Preview: Pass tax.name to InvoiceLine 2024-02-23 10:53:01 +01:00
Raphael Michel
56e0ab8378 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5562 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-02-22 10:16:54 +01:00
Raphael Michel
a9ae237b1a Translations: Update German (informal) (de_Informal)
Currently translated at 99.8% (5556 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-02-22 10:16:54 +01:00
Raphael Michel
27823b7bf6 Translations: Update German
Currently translated at 100.0% (5562 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-02-22 10:16:54 +01:00
Raphael Michel
4231cd2576 Translations: Update German (informal) (de_Informal)
Currently translated at 99.7% (5547 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-02-22 10:16:54 +01:00
Raphael Michel
6aa5196f18 Translations: Update German
Currently translated at 99.7% (5547 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-02-22 10:16:54 +01:00
Wikinaut
c1eac5e91e Translations: Update German
Currently translated at 99.7% (5547 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-02-22 10:16:54 +01:00
Marco Addario
410e06364a Translations: Update Italian
Currently translated at 20.9% (1166 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/it/

powered by weblate
2024-02-22 10:16:54 +01:00
fyksen
ae137f8f16 Translations: Update Norwegian Bokmål
Currently translated at 98.0% (5452 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nb_NO/

powered by weblate
2024-02-22 10:16:54 +01:00
Mark Leenen
f9f3f9f868 Translations: Update Dutch
Currently translated at 83.0% (4621 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-02-22 10:16:54 +01:00
fyksen
395eadde47 Translations: Update Norwegian Bokmål
Currently translated at 92.8% (5166 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nb_NO/

powered by weblate
2024-02-22 10:16:54 +01:00
Raphael Michel
2be790fa45 Sendmail: Allow to copy rules 2024-02-22 09:43:40 +01:00
Raphael Michel
f9d78eaf1a CachedFileField: Do not store file that does not pass validation 2024-02-21 14:32:23 +01:00
Mira Weller
2d5d27e950 forms: fix image file upload in CachedFileField 2024-02-21 14:32:23 +01:00
Mira Weller
c6fa19d771 forms: fix bound data retrieval of CachedFile
when re-submitting a form a second time, the cached file got lost
2024-02-21 14:32:23 +01:00
Mira Weller
3129253eef forms: fix file type validation on CachedFileInput 2024-02-21 14:32:23 +01:00
Raphael Michel
b69ab86458 Stripe: Fix crash in data shredder 2024-02-21 13:40:31 +01:00
Martin Gross
80f7ae0b76 Docs: Remove stray line from page restructuring (Fixes #3925) 2024-02-19 21:34:59 +01:00
Martin Gross
160f9a4363 Revert "Update pypdf requirement from ==3.9.* to ==4.0.* (#3903)"
This reverts commit a3586a73f1.
2024-02-17 14:37:49 +01:00
dependabot[bot]
24b5b9373d Update libsass requirement from ==0.22.* to ==0.23.* (#3918)
---
updated-dependencies:
- dependency-name: libsass
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 20:14:19 +01:00
dependabot[bot]
178c40aee6 Update dnspython requirement from ==2.3.* to ==2.5.* (#3917)
Updates the requirements on [dnspython](https://github.com/rthalley/dnspython) to permit the latest version.
- [Release notes](https://github.com/rthalley/dnspython/releases)
- [Changelog](https://github.com/rthalley/dnspython/blob/master/doc/whatsnew.rst)
- [Commits](https://github.com/rthalley/dnspython/compare/v2.3.0rc1...v2.5.0)

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 20:13:46 +01:00
dependabot[bot]
49c41878d2 Update protobuf requirement from ==4.23.* to ==4.25.* (#3916)
Updates the requirements on [protobuf](https://github.com/protocolbuffers/protobuf) to permit the latest version.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.23.0-rc1...v4.25.2)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 20:13:34 +01:00
Raphael Michel
fa4c29cf23 Check-in: Fix crash on medium scan that is mapped to wrong event (PRETIXEU-9P0) 2024-02-15 14:46:24 +01:00
Raphael Michel
75b93eebc5 Order change form: Show attendee names 2024-02-15 14:22:48 +01:00
dependabot[bot]
5a406abdd6 Update reportlab requirement from ==4.0.* to ==4.1.* (#3906)
Updates the requirements on [reportlab](https://www.reportlab.com/) to permit the latest version.

---
updated-dependencies:
- dependency-name: reportlab
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 14:17:06 +01:00
Raphael Michel
6712baf534 Invoice creation: Fix duplicate new lines 2024-02-15 14:10:49 +01:00
Raphael Michel
4d9243151f Invoice creation: Fix duplicate new lines 2024-02-15 14:10:15 +01:00
Raphael Michel
b89a4f7b32 Update css-inline requirement from ==0.8.* to ==0.13.* 2024-02-15 13:49:03 +01:00
Raphael Michel
c80d5b1bb2 Update flake8 requirement from ==6.0.* to ==7.0.* 2024-02-15 13:49:03 +01:00
dependabot[bot]
0334c2f433 Update django-hijack requirement from ==3.3.* to ==3.4.* (#3909)
Updates the requirements on [django-hijack](https://github.com/django-hijack/django-hijack) to permit the latest version.
- [Release notes](https://github.com/django-hijack/django-hijack/releases)
- [Changelog](https://github.com/django-hijack/django-hijack/blob/master/docs/release-button.png)
- [Commits](https://github.com/django-hijack/django-hijack/compare/3.3.0...3.4.5)

---
updated-dependencies:
- dependency-name: django-hijack
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 13:48:56 +01:00
dependabot[bot]
6bc46b7aec Update django-otp requirement from ==1.2.* to ==1.3.* (#3908)
Updates the requirements on [django-otp](https://github.com/django-otp/django-otp) to permit the latest version.
- [Changelog](https://github.com/django-otp/django-otp/blob/master/CHANGES.rst)
- [Commits](https://github.com/django-otp/django-otp/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: django-otp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 13:48:28 +01:00
dependabot[bot]
3ebe622189 Update pillow requirement from ==9.5.* to ==10.2.* (#3905)
Updates the requirements on [pillow](https://github.com/python-pillow/Pillow) to permit the latest version.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.5.0...10.2.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 13:45:49 +01:00
dependabot[bot]
25fb1ee3be Update pytest-xdist requirement from ==3.3.* to ==3.5.* (#3896)
Updates the requirements on [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest-xdist/releases)
- [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.3.0...v3.5.0)

---
updated-dependencies:
- dependency-name: pytest-xdist
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 13:44:25 +01:00
dependabot[bot]
a3586a73f1 Update pypdf requirement from ==3.9.* to ==4.0.* (#3903)
Updates the requirements on [pypdf](https://github.com/py-pdf/pypdf) to permit the latest version.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/3.9.0...4.0.1)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 13:44:15 +01:00
Raphael Michel
93eb041acc Quota item selection: Strike disabled items in select2 2024-02-14 16:38:53 +01:00
Raphael Michel
63894ca3da Update django-bootstrap3 requirement from ==23.1.* to ==23.6 (#3894)
* Update django-bootstrap3 requirement from ==23.1.* to ==23.6

 Removing our previous workarounds

* Fix import
2024-02-14 14:35:45 +01:00
dependabot[bot]
73b2cce435 Update fakeredis requirement from ==2.18.* to ==2.21.* (#3899)
Updates the requirements on [fakeredis](https://github.com/cunla/fakeredis-py) to permit the latest version.
- [Release notes](https://github.com/cunla/fakeredis-py/releases)
- [Commits](https://github.com/cunla/fakeredis-py/compare/v2.18.0...v2.21.0)

---
updated-dependencies:
- dependency-name: fakeredis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 13:28:40 +01:00
dependabot[bot]
0a711f4965 Bump markdown from 3.4.3 to 3.5.2 (#3898)
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.4.3 to 3.5.2.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.4.3...3.5.2)

---
updated-dependencies:
- dependency-name: markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 13:28:34 +01:00
dependabot[bot]
75bf200aac Update pytest-mock requirement from ==3.10.* to ==3.12.* (#3901)
Updates the requirements on [pytest-mock](https://github.com/pytest-dev/pytest-mock) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.10.0...v3.12.0)

---
updated-dependencies:
- dependency-name: pytest-mock
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 13:28:21 +01:00
dependabot[bot]
11307de30a Update pytest requirement from ==7.3.* to ==8.0.* (#3902)
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.0...8.0.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 13:28:14 +01:00
dependabot[bot]
863db60786 Update pycryptodome requirement from ==3.18.* to ==3.20.* (#3904)
Updates the requirements on [pycryptodome](https://github.com/Legrandin/pycryptodome) to permit the latest version.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/compare/v3.18.0x...v3.20.0)

---
updated-dependencies:
- dependency-name: pycryptodome
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 13:27:55 +01:00
Wessel Stam
f5a1adedca Translations: Update Dutch (informal) (nl_Informal)
Currently translated at 72.2% (4017 of 5562 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl_Informal/

powered by weblate
2024-02-14 13:27:43 +01:00
Raphael Michel
ea74688633 API: Expose OrderPosition.voucher_budget_use (#3867) 2024-02-14 13:27:30 +01:00
Raphael Michel
57738f19bf Update webauthn requirement from ==0.4.* to ==2.0.* (#3880)
* Get rid of unmaintained dependency python-u2flib-server

* Update webauthn requirement from ==0.4.* to ==2.0.*

* Fix tests

* Update src/pretix/control/views/auth.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/views/auth.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/views/user.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/views/user.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/views/user.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-02-14 13:27:24 +01:00
Richard Schreiber
7b5ce5e198 Select2: add option to close when clearing selection (#3870) 2024-02-13 22:27:36 +01:00
Richard Schreiber
d5f9beef69 PDF-Editor: improve grouping of object attribute inputs (#3881) 2024-02-13 22:26:30 +01:00
Mira
eee39b1300 Widget: fix availability of variations whose base item is unavailable (#3873)
* widget: fix variation/item unavailability

In case of an item variation, check the unavailability reasons of the item itself
as well as the variation.

* widget: Don't display waiting list on otherwise unavailable items
2024-02-13 22:25:08 +01:00
dependabot[bot]
c2fdea020d Update django-phonenumber-field requirement from ==7.1.* to ==7.3.* (#3891)
Updates the requirements on [django-phonenumber-field](https://github.com/stefanfoulis/django-phonenumber-field) to permit the latest version.
- [Release notes](https://github.com/stefanfoulis/django-phonenumber-field/releases)
- [Changelog](https://github.com/stefanfoulis/django-phonenumber-field/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/stefanfoulis/django-phonenumber-field/compare/7.1.0...7.3.0)

---
updated-dependencies:
- dependency-name: django-phonenumber-field
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 13:38:20 +01:00
Raphael Michel
f87e089734 Update django-oauth-toolkit requirement from ==2.2.* to ==2.3.* (#3882) 2024-02-13 12:34:29 +01:00
dependabot[bot]
0fad7472c0 Bump django-filter from 23.2 to 23.5 (#3889)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 23.2 to 23.5.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/23.2...23.5)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 12:29:39 +01:00
dependabot[bot]
bd0a223066 Update pyjwt requirement from ==2.7.* to ==2.8.* (#3892)
Updates the requirements on [pyjwt](https://github.com/jpadilla/pyjwt) to permit the latest version.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.7.0...2.8.0)

---
updated-dependencies:
- dependency-name: pyjwt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:53:42 +01:00
dependabot[bot]
782c1a5d39 Update isort requirement from ==5.12.* to ==5.13.* (#3884)
Updates the requirements on [isort](https://github.com/pycqa/isort) to permit the latest version.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.12.0...5.13.2)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:53:19 +01:00
dependabot[bot]
5c99d3bf69 Update django-compressor requirement from ==4.3.* to ==4.4 (#3888)
Updates the requirements on [django-compressor](https://github.com/django-compressor/django-compressor) to permit the latest version.
- [Changelog](https://github.com/django-compressor/django-compressor/blob/develop/docs/changelog.txt)
- [Commits](https://github.com/django-compressor/django-compressor/compare/4.3...4.4)

---
updated-dependencies:
- dependency-name: django-compressor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:52:59 +01:00
dependabot[bot]
5e6307acc9 Update chardet requirement from ==5.1.* to ==5.2.* (#3887)
Updates the requirements on [chardet](https://github.com/chardet/chardet) to permit the latest version.
- [Release notes](https://github.com/chardet/chardet/releases)
- [Commits](https://github.com/chardet/chardet/compare/5.1.0...5.2.0)

---
updated-dependencies:
- dependency-name: chardet
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:52:51 +01:00
dependabot[bot]
d4bfa9d773 Update redis requirement from ==4.6.* to ==5.0.* (#3886)
Updates the requirements on [redis](https://github.com/redis/redis-py) to permit the latest version.
- [Release notes](https://github.com/redis/redis-py/releases)
- [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES)
- [Commits](https://github.com/redis/redis-py/compare/v4.6.0...v5.0.1)

---
updated-dependencies:
- dependency-name: redis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:52:44 +01:00
dependabot[bot]
b7f540251c Update sphinx requirement from ==7.0.* to ==7.2.* (#3885)
Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx) to permit the latest version.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.0.0rc1...v7.2.6)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 10:52:35 +01:00
Phin Wolkwitz
cb17d80b63 Widget: Fix variations collapse indicator placement (#3883) 2024-02-12 13:51:25 +01:00
Raphael Michel
86b28b9b53 Get rid of unmaintained dependency python-u2flib-server (#3879) 2024-02-12 13:03:56 +01:00
dependabot[bot]
fac404631c Update sentry-sdk requirement from ==1.15.* to ==1.40.* (#3850)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.15.0...1.40.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 12:53:01 +01:00
Phin Wolkwitz
fd547014a9 Translations: Update German (informal) (de_Informal)
Currently translated at 99.1% (223 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2024-02-12 10:17:44 +01:00
Phin Wolkwitz
d23a625415 Translations: Update German
Currently translated at 99.1% (223 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2024-02-12 10:17:44 +01:00
dependabot[bot]
199416b904 Update django-redis requirement from ==5.2.* to ==5.4.* (#3877)
Updates the requirements on [django-redis](https://github.com/jazzband/django-redis) to permit the latest version.
- [Release notes](https://github.com/jazzband/django-redis/releases)
- [Changelog](https://github.com/jazzband/django-redis/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jazzband/django-redis/compare/5.2.0...5.4.0)

---
updated-dependencies:
- dependency-name: django-redis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 10:01:52 +01:00
dependabot[bot]
0a7a113b4e Update pytest-rerunfailures requirement from ==11.* to ==13.* (#3878)
Updates the requirements on [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) to permit the latest version.
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/11.0...13.0)

---
updated-dependencies:
- dependency-name: pytest-rerunfailures
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:47:04 +01:00
dependabot[bot]
5978a715b5 Update aiohttp requirement from ==3.8.* to ==3.9.* (#3875)
Updates the requirements on [aiohttp](https://github.com/aio-libs/aiohttp) to permit the latest version.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.0a0...v3.9.3)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:41:41 +01:00
dependabot[bot]
71beb54eb4 Bump django-formtools from 2.4.1 to 2.5.1 (#3876)
Bumps [django-formtools](https://github.com/jazzband/django-formtools) from 2.4.1 to 2.5.1.
- [Changelog](https://github.com/jazzband/django-formtools/blob/master/docs/changelog.rst)
- [Commits](https://github.com/jazzband/django-formtools/compare/2.4.1...2.5.1)

---
updated-dependencies:
- dependency-name: django-formtools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:35:10 +01:00
dependabot[bot]
b92981353f Update django-statici18n requirement from ==2.3.* to ==2.4.* (#3874)
Updates the requirements on [django-statici18n](https://github.com/zyegfryed/django-statici18n) to permit the latest version.
- [Changelog](https://github.com/zyegfryed/django-statici18n/blob/main/docs/changelog.rst)
- [Commits](https://github.com/zyegfryed/django-statici18n/commits)

---
updated-dependencies:
- dependency-name: django-statici18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:34:55 +01:00
Raphael Michel
a5f7115e19 Allow dependabot to create more PRs (as we already have 5 long-running) 2024-02-12 09:08:12 +01:00
Raphael Michel
f5e3d4b0bc API: Fix logging of event deletion 2024-02-09 17:27:08 +01:00
Raphael Michel
6fba080b8f Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-02-09 15:51:35 +01:00
Phin Wolkwitz
365ccf159e Widget: Change text when expanding variations (Z#23141075) (#3852)
* Add text change to variation toggle
* Add svg caret
* Fix svg and css
* update caret-svg, add fill-link-color and animation
* Use computed property for link text
* Rename variable according to code review
* Improve texts

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-02-09 13:29:40 +01:00
Raphael Michel
b40a41d742 OrderListExporter: Refactor querysets out of iterate methods 2024-02-09 12:03:26 +01:00
Martin Gross
bf1081071b CheckinlistPDF: Export attendee company based on op; fallback to IA (Z#23144201) (#3869)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-02-09 10:10:45 +01:00
Phin Wolkwitz
e261ce7554 Fix key error on copy_from (PRETIXEU-9NR) (#3868) 2024-02-08 17:34:24 +01:00
Raphael Michel
7cae0ceab8 Fix migration of old hide_without_voucher products 2024-02-08 13:08:13 +01:00
Mie Frydensbjerg
064ee91225 Translations: Update Danish
Currently translated at 31.3% (1740 of 5550 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2024-02-08 12:55:10 +01:00
Raphael Michel
495b3ec770 API: Log ID of revoked device connection 2024-02-08 10:09:28 +01:00
Phin Wolkwitz
39f9329207 Quota form: Change item selection field per context (#3839)
* Change item checkbox select to multiselect widget

* Make item selection widget dependent on count

* Make item selection widget dependent on variable

* Adjust widget choices

* Fix widget choices

* Fix item variation key errors

* Simplify code

* Fix classname

* Improve argument name

* Fix widget name
2024-02-08 09:33:39 +01:00
Raphael Michel
2b72cfdaff Fix cration of variations 2024-02-07 10:58:56 +01:00
Raphael Michel
70d32ea1aa Voucher form: Add quota in help text 2024-02-07 09:59:32 +01:00
Till Kemper
0871482681 Add product variation to addon-label when modifying order (#3864)
* Added Variation of Product by Additional Products

at Postion Name by Additional Products the Variant should missing. added it with the prefix -

* Update src/pretix/presale/templates/pretixpresale/event/order_modify.html

---------

Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
2024-02-07 09:48:01 +01:00
Raphael Michel
5d4f3eab06 Stripe: Add link to Stripe App (#3860) 2024-02-06 17:48:13 +01:00
Mira
fa3265b1fb Let plugins prevent the download of individual tickets in an order (#3858)
* Let plugins allow/prevent the download of individual tickets in an order (#3836)

(extends the functionality of the allow_ticket_download signal)

(cherry picked from commit e20edab98f)

* fix bug where in some cases, only the first ticket could be downloaded
2024-02-06 17:35:59 +01:00
Richard Schreiber
92e6ffc7ef Fix widget unavailability_reason 2024-02-06 13:55:34 +01:00
Mira
22f91f7aa2 Improve UI to configure unavailable items handling (Z#23131828) (#3739)
* start impl of unavailability modes ui

* add db migration

* use new widget for more fields

* improve contrast

* use new widget for hide_without_voucher field

* improved wording

* rebase migration

* undo changes to require_membership_hidden

* code formatting

* move unavail_reason logic around

* enforce consistent state of hide_without_voucher / require_voucher

* annotate unavailability info in get_grouped_items

* remove MSIE6 compat

* add unavailability reasons to widget

* remove test output

* Apply suggestions from code review

text improvements

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* add css fix for jumping items due to tooltip

* dynamically retrieve unavailability reason message

* widget: simplify logic conditions

* add available_{from,until}_mode to api and api docs

* rebase migration

* rebase migration

* add unavailable_*_mode to ItemVariation

* add available_*_mode to API docs for items

* fix wrong reference

* fix test cases

* add available_*_mode to item variation form

* apply unavailability modes to subevents and variations (presale)

* /o\

* apply unavailability modes to subevents and variations (widget)

* display unavailability mode in subevent product settings

* fix widget test

* fix api item tests

* copy available_*_mode when copying an item

* Apply suggestions from code review

Co-authored-by: Raphael Michel <michel@rami.io>

* Add unavail mode indicator to bulk create and edit forms

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: Raphael Michel <michel@rami.io>
2024-02-06 12:27:19 +01:00
dependabot[bot]
43facd1e43 Bump @babel/core from 7.23.7 to 7.23.9 in /src/pretix/static/npm_dir (#3854)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.23.7 to 7.23.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.9/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 11:54:57 +01:00
Martin Gross
11242a2325 Docs/Widget: Add Payment Method Domain Registration Instructions (Z#23143782) (#3861)
* Docs/Widget: Add Payment Method Domain Registration Instructions

* Rephrase
2024-02-06 11:38:32 +01:00
Richard Schreiber
28db9a5262 Fix item column overflow in order-overview PDF-report (#3857)
* Fix automatic line-break in order-overview PDF-report

* vertical align top
2024-02-06 11:37:57 +01:00
Raphael Michel
57e8c6aafd Fix #3856 -- Clarify label in sendmail form 2024-02-06 11:35:55 +01:00
dependabot[bot]
fa47f63307 Bump @babel/preset-env from 7.23.7 to 7.23.9 in /src/pretix/static/npm_dir (#3855)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.23.7 to 7.23.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.9/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 11:33:13 +01:00
Mira
bac673f3ab Allow template syntax in event text (Z#23140046) (#3815)
* remove duplicate context generation

* allow text templates in frontpage_text

* refactor: move placeholder functionality to separate file

* fix wrong class name, code style

* update year in license header

* undo license header update

* use new function name

* render only the placeholders that are actually used in the message

* refactoring

* add str(...) call

* Update doc/development/api/placeholder.rst

Co-authored-by: Raphael Michel <michel@rami.io>

* rename register_mail_placeholders to register_template_placeholders
(deprecate old name)

* isort

* add signals to docs

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2024-02-06 11:32:03 +01:00
Martin Gross
45ac391998 BasePaymentProvider: skip country check if ia.country == '' (Z#23143749) (#3859) 2024-02-05 16:51:04 +01:00
Martin Gross
fed5097708 CheckIn: Only run check_rules_qs conditionally on provided boolean 2024-02-05 14:01:42 +01:00
Martin Gross
9d115c30d7 Revert "Let plugins allow/prevent the download of individual tickets in an order (#3836)"
This reverts commit e20edab98f.
2024-02-02 16:09:42 +01:00
Martin Gross
a769da62c7 Addresses: Add Federal Territories to state dropdown for MY. 2024-02-02 12:31:06 +01:00
Mira
e20edab98f Let plugins allow/prevent the download of individual tickets in an order (#3836)
(extends the functionality of the allow_ticket_download signal)
2024-02-01 17:45:58 +01:00
Pavle Ergović
4f4fcb84ce Translations: Update Croatian
Currently translated at 1.3% (3 of 221 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/hr/

powered by weblate
2024-01-31 14:25:07 +01:00
Pavle Ergović
6560d161c9 Translations: Update Croatian
Currently translated at 0.1% (4 of 5550 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/hr/

powered by weblate
2024-01-31 14:25:07 +01:00
Eduardo Fernandez
7f23c590ca Translations: Update Spanish
Currently translated at 89.2% (4954 of 5550 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-01-31 14:25:07 +01:00
Raphael Michel
0ca33eddb1 Cart: More useful error message if some selected products are sold (#3848)
* Cart: More useful error message if some selected products are sold

* Update src/pretix/base/services/cart.py

Co-authored-by: Mira <weller@rami.io>

---------

Co-authored-by: Mira <weller@rami.io>
2024-01-31 14:23:07 +01:00
Raphael Michel
45341c4a31 Translations: Update German
Currently translated at 100.0% (5550 of 5550 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-01-30 17:37:50 +01:00
Raphael Michel
5de5ae4ca2 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5550 of 5550 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-01-30 17:37:50 +01:00
Raphael Michel
03f71f3cdf Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-01-30 17:10:54 +01:00
Candide U
f97ad66026 Add formats for en_CA (#3844)
* Create __init__.py

* Create formats.py for Canadian English

Referencing: https://github.com/pretix/pretix/discussions/3842


Based on:

- https://github.com/pretix/pretix/blob/master/src/pretix/helpers/formats/en_US/formats.py (for time formatting and structure)

- https://github.com/django/django/blob/main/django/conf/locale/fr_CA/formats.py (For dates)

* Update __init__.py

---------

Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
2024-01-30 17:03:39 +01:00
Raphael Michel
31392e5852 Add simplified invoice renderer (#3846) 2024-01-30 16:14:53 +01:00
Raphael Michel
77a5a685f1 Bank transfer: Clarify instructions on pending payment (#3845) 2024-01-30 16:14:21 +01:00
Raphael Michel
2b77e59e0a Fix #3838 -- String not in translation 2024-01-30 12:16:09 +01:00
Raphael Michel
70f755599a Add "lead" to slug banlist 2024-01-30 10:10:47 +01:00
Raphael Michel
2a76b2a5dd Docs: Add new exhibitor API fields 2024-01-30 10:08:19 +01:00
Raphael Michel
ffea243eae Bank transfer: Fix invoice address not existing (PRETIXEU-9M1) 2024-01-29 16:20:38 +01:00
Raphael Michel
a4012e6100 Remove nl_BE *again* 2024-01-29 14:53:45 +01:00
Raphael Michel
9bd250f9fc Bump version to 2024.2.0.dev0 2024-01-29 13:47:00 +01:00
Raphael Michel
7f93fb6b4d Bump version to 2024.1.0 2024-01-29 13:46:05 +01:00
Raphael Michel
1b3f27852d Calendar: Fix week day header for incomplete months 2024-01-29 13:32:36 +01:00
Raphael Michel
fab29088e6 Event calendar: Don't skip week if it is still sunday 2024-01-29 12:57:35 +01:00
Raphael Michel
9feea75bdb Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5546 of 5546 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-01-29 12:29:38 +01:00
Raphael Michel
52f08c818f Translations: Update German
Currently translated at 100.0% (5546 of 5546 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-01-29 12:29:38 +01:00
Raphael Michel
e89483e3f2 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-01-29 12:17:07 +01:00
Raphael Michel
467469f26d Fix typo 2024-01-29 10:35:40 +01:00
Mira
aa9d526207 Allow consistent deep links to tabs (#3840) 2024-01-29 09:38:41 +01:00
Eduardo Fernandez
3338858420 Translations: Update Spanish
Currently translated at 88.9% (4937 of 5548 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-01-29 09:32:59 +01:00
BMaster
3e758c6a1c Translations: Update Dutch
Currently translated at 83.2% (4617 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-01-29 09:32:59 +01:00
Ryo
fc7e69523c Translations: Update Japanese
Currently translated at 3.1% (172 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2024-01-29 09:32:59 +01:00
BerkieBb
3289b4411a Translations: Update Dutch
Currently translated at 83.1% (4613 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-01-29 09:32:59 +01:00
Alain
5c98512241 Translations: Update Dutch
Currently translated at 83.1% (4613 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-01-29 09:32:59 +01:00
Freek Engelbarts
3ca22933f4 Translations: Update Dutch
Currently translated at 83.1% (4613 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-01-29 09:32:59 +01:00
BMaster
106d3f3c74 Translations: Update Dutch
Currently translated at 83.1% (4613 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/nl/

powered by weblate
2024-01-29 09:32:59 +01:00
Raphael Michel
15d3fbc02e Fix auto-selected date in calendar with long-running events (Z#23141457) (#3829)
* Fix auto-selected date in calendar with long-running events (Z#23141457)

* Review fixes

* Update src/pretix/presale/views/organizer.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-01-26 19:22:45 +01:00
Raphael Michel
eaae7e9ea2 Allow to set amount and date when manually confirming a payment (#3828)
* Allow to set amount and date when manually confirming a payment

* Fix tests
2024-01-26 19:22:15 +01:00
Raphael Michel
9eb1c5047b Subevent bulk creation: Handle available_from of items the same way as dates (#3822) 2024-01-26 19:20:34 +01:00
Raphael Michel
25d4b603be Docs: Add note on where to set up meta data 2024-01-26 11:48:46 +01:00
Raphael Michel
eac88b5ef7 Widget: Fix language on first iframe request 2024-01-26 11:44:02 +01:00
Raphael Michel
734b376e05 Push missing file 2024-01-26 11:28:52 +01:00
Raphael Michel
2354affde7 API: Fix CSRF support for session-based usage 2024-01-26 11:20:56 +01:00
Martin Gross
11e922b1a9 Teams: Link email to user for superusers 2024-01-25 12:22:35 +01:00
Raphael Michel
b7f0c3cc6c Fix cookie detection 2024-01-25 10:35:26 +01:00
Kian Cross
f9f629299b Ensure customer_signed_in signal is fired for popup login (#3835)
In a7f7c64, a `customer_signed_in` in signal was introduced. However,
when a user currently logs in using a popup, the signal is not fired.
This commit resolves this.
2024-01-25 10:03:50 +01:00
Raphael Michel
645c9d5900 Add "Partitioned" flag to our cookies (#3830) 2024-01-25 09:46:04 +01:00
Raphael Michel
6af2d38a98 Add __Host- prefix to CSRF and session cookie, remove cookie_domain (#3831)
* Add __Host- prefix to CSRF and session cookie, remove cookie_domain

* Fix tests
2024-01-25 09:45:56 +01:00
Raphael Michel
dba8e80868 Delete nl_BE again 2024-01-24 17:48:53 +01:00
Raphael Michel
324ff2ab67 Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5545 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2024-01-24 16:48:09 +01:00
Raphael Michel
5ea09a5b0a Translations: Update German
Currently translated at 100.0% (5545 of 5545 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2024-01-24 16:48:09 +01:00
Eduardo Fernandez
c046caa894 Translations: Update Spanish
Currently translated at 88.4% (4898 of 5535 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2024-01-24 16:48:09 +01:00
Raphael Michel
be8197825c Translations: Update wordlist 2024-01-24 16:30:38 +01:00
Raphael Michel
d48c28bec7 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2024-01-24 14:03:24 +01:00
Raphael Michel
b07c1802a0 Add limits to gift card length 2024-01-24 14:02:54 +01:00
Raphael Michel
7f0cf1655a Stripe/PayPal: Add explanatory texts (Z#23127572) (#3826) 2024-01-24 14:02:44 +01:00
Phin Wolkwitz
0a154dc79f Presale: Fix booking period error message logic (Z#23115841) (#3832)
* Fix presale start and end error message logic

* Improve readability
2024-01-23 15:58:35 +01:00
Raphael Michel
7022e5bf49 Add missing entries to POS security profile 2024-01-23 11:40:41 +01:00
649 changed files with 387461 additions and 248315 deletions

View File

@@ -10,7 +10,9 @@ 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

View File

@@ -26,12 +26,12 @@ jobs:
matrix:
python-version: ["3.11"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

View File

@@ -25,12 +25,12 @@ jobs:
name: Spellcheck
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-22.04
name: Check gettext syntax
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -48,12 +48,12 @@ jobs:
runs-on: ubuntu-22.04
name: Spellcheck
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

View File

@@ -23,12 +23,12 @@ jobs:
name: isort
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -43,12 +43,12 @@ jobs:
name: flake8
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -63,9 +63,9 @@ jobs:
name: licenseheaders
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install Dependencies

View File

@@ -5,7 +5,6 @@ on:
branches: [ master ]
paths-ignore:
- 'doc/**'
- 'src/pretix/locale/**'
pull_request:
branches: [ master ]
paths-ignore:
@@ -32,7 +31,7 @@ jobs:
- database: sqlite
python-version: "3.10"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: harmon758/postgresql-action@v1
with:
postgresql version: '15'
@@ -41,10 +40,10 @@ jobs:
postgresql password: 'postgres'
if: matrix.database == 'postgres'
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

View File

@@ -1,29 +1,30 @@
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:
- virtualenv env
- source env/bin/activate
- pip install -U pip wheel setuptools
- XDG_CACHE_HOME=/cache pip3 install -e ".[dev]"
- uv pip install --system -e ".[dev]"
- cd src
- python manage.py check
- make all compress
- py.test --reruns 3 -n 3 tests
tags:
- python3
- PRETIX_CONFIG_FILE=tests/travis_sqlite.cfg py.test --reruns 3 -n 3 tests --maxfail=100
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:
- 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]"
- uv pip install --system -e ".[dev]"
- python setup.py sdist
- pip install dist/pretix-*.tar.gz
- uv pip install --system dist/pretix-*.tar.gz
- python -m pretix migrate
- python -m pretix check
- cd src
@@ -33,13 +34,12 @@ pypi:
- python -m build
- twine check dist/*
- twine upload dist/*
tags:
- python3
only:
- pypi
artifacts:
paths:
- src/dist/
stages:
- test
- build

1
.node-version Normal file
View File

@@ -0,0 +1 @@
17

View File

@@ -10,6 +10,8 @@ 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 *

View File

@@ -47,7 +47,7 @@ if [ "$1" == "taskworker" ]; then
fi
if [ "$1" == "upgrade" ]; then
exec python3 -m pretix updatestyles
exec python3 -m pretix updateassets
fi
exec python3 -m pretix "$@"

View File

@@ -42,7 +42,6 @@ Example::
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``
@@ -53,10 +52,18 @@ Example::
``currency``
The default currency as a three-letter code. Defaults to ``EUR``.
``cachedir``
The local path to a directory where temporary files will be stored.
Defaults to the ``cache`` directory below the ``datadir``.
``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``.
``logdir``
The local path to a directory where log files will be stored.
Defaults to the ``logs`` directory below the ``datadir``.
``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``.
@@ -71,9 +78,6 @@ Example::
``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 ``off``.
@@ -93,8 +97,9 @@ Example::
Defaults to ``off``.
``obligatory_2fa``
Enables or disables obligatory usage of Two-Factor Authentication for users of the pretix backend.
Defaults to ``False``
Enables or disables obligatory usage of two-factor authentication for users of the pretix backend.
Can be ``True`` to make two-factor authentication obligatory for all users or ``staff`` to make it only
obligatory to users with admin permissions. 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
@@ -153,6 +158,7 @@ Example::
host=localhost
port=3306
advisory_lock_index=1
disable_server_side_cursors=0
sslmode=require
sslrootcert=/etc/pretix/postgresql-ca.crt
sslcert=/etc/pretix/postgresql-client-crt.crt
@@ -173,6 +179,11 @@ Example::
and are not scoped to a specific database. If you run multiple pretix applications with the same PostgreSQL server,
you should set separate values for this setting (integers up to 256).
``disable_server_side_cursors``
On PostgreSQL pretix might use server side cursors for certain operations. This is generally fine but will break in
specific circumstances, for example when connecting to PostgreSQL through a PGBouncer configured with a transaction
pool mode. Off by default (i.e. by default server side cursors will be used).
``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.
@@ -349,7 +360,7 @@ to speed up various operations::
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``
``sessions``
When this is set to ``True``, redis will be used as the session storage.
``sentinels``
@@ -525,4 +536,4 @@ pretix can optionally make use of a GeoIP database for some features. It needs a
.. _GeoAcumen: https://github.com/geoacumen/geoacumen-country
.. _GeoLite2: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
.. _GeoLite2: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data

View File

@@ -0,0 +1,18 @@
.. highlight:: none
.. _`community`:
Community install guides
========================
.. warning:: The guides are maintained by the community and not by the pretix core team. If you encounter any issues with the guides, please report them to the maintainers of the guides. The pretix core team can not provide support for installs using these guides.
Kubernetes
----------
- Helm Chart by techwolf12 - A Helm chart for deploying pretix on Kubernetes. The chart documentation is available on `ArtifactHub <https://artifacthub.io/packages/helm/techwolf12/pretix>`_ and the source code is available on `GitHub <https://github.com/Techwolf12/charts/tree/main/pretix-helm>`_.
Docker
------
- `docker compose setup <https://github.com/ZPascal/pretix-docker-compose>`_ by ZPascal

View File

@@ -19,7 +19,7 @@ You can use ``pip`` to update pretix directly to the development branch. Then, u
(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
(venv)$ python -m pretix updateassets
# systemctl restart pretix-web pretix-worker
Docker installation

View File

@@ -14,3 +14,4 @@ for your needs.
manual_smallscale
dev_version
enterprise
community

View File

@@ -65,7 +65,7 @@ Package dependencies
To build and run pretix, you will need the following debian packages::
# apt-get install git build-essential python3-dev python3-venv python3 python3-pip \
python3-dev libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
gettext libpq-dev libjpeg-dev libopenjp2-7-dev
Config file
@@ -120,6 +120,7 @@ Now we will install pretix itself. The following steps are to be executed as the
actually install pretix, we will create a virtual environment to isolate the python packages from your global
python installation::
# sudo -u pretix -s
$ python3 -m venv /var/pretix/venv
$ source /var/pretix/venv/bin/activate
(venv)$ pip3 install -U pip setuptools wheel
@@ -279,11 +280,12 @@ Updates
To upgrade to a new pretix release, pull the latest code changes and run the following commands::
# sudo -u pretix -s
$ 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
(venv)$ python -m pretix updateassets
# 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. Pay special
@@ -323,7 +325,7 @@ Then, proceed like after any plugin installation::
(venv)$ python -m pretix migrate
(venv)$ python -m pretix rebuild
(venv)$ python -m pretix updatestyles
(venv)$ python -m pretix updateassets
# 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

View File

@@ -103,6 +103,12 @@ pretix_celery_tasks_queued_count
pretix_celery_tasks_queued_age_seconds
The age of the longest-waiting in the worker queue in seconds, labeled with ``queue``.
pretix_logins_successful
Counter. The number of successful backend logins.
pretix_logins_failed
Counter. The number of failed backend logins, labeled with ``reason``.
.. _metric types: https://prometheus.io/docs/concepts/metric_types/
.. _Prometheus: https://prometheus.io/
.. _cProfile: https://docs.python.org/3/library/profile.html

View File

@@ -73,4 +73,11 @@ This release includes a migration that changes retroactively fills an `organizer
`pretixbase_logentry`. If you have a large database, the migration step of the upgrade might take significantly
longer than usual, so plan the update accordingly.
Upgrade to 2024.7.0 or newer
"""""""""""""""""""""""""""""
This release includes a migration that changes how sales channels are referred on orders.
If you have a large database, the migration step of the upgrade might take significantly longer than usual, so plan
the update accordingly.
.. _blog: https://pretix.eu/about/en/blog/

View File

@@ -249,7 +249,10 @@ You can get three response codes:
Content-Type: application/json
{
"event": "democon",
"event": {
"name": "Demo Conference",
"slug": "democon"
},
"subevent": 23,
"checkinlist": 5
}

View File

@@ -94,7 +94,9 @@ 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`` or ``https://example.org/order/``.
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.
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

View File

@@ -0,0 +1,259 @@
.. _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.

View File

@@ -40,6 +40,11 @@ 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
===================================== ========================== =======================================================

View File

@@ -32,6 +32,7 @@ position_count integer Number of ticke
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.
**Deprecated, will be removed in pretix 2024.10.** Use :ref:`rest-autocheckinrules`: instead.
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.

View File

@@ -19,6 +19,7 @@ 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
@@ -39,6 +40,10 @@ 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
---------
@@ -71,6 +76,7 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"phone": "+493012345678",
"name": "John Doe",
"name_parts": {
"_scheme": "full",
@@ -118,6 +124,7 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"phone": "+493012345678",
"name": "John Doe",
"name_parts": {
"_scheme": "full",
@@ -155,6 +162,7 @@ Endpoints
{
"email": "test@example.org",
"phone": "+493012345678",
"password": "verysecret",
"send_email": true
}
@@ -171,6 +179,7 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
"phone": "+493012345678",
...
}
@@ -215,6 +224,7 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
"phone": "+493012345678",
}
@@ -249,6 +259,7 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": null,
"phone": null,
}

View File

@@ -20,8 +20,12 @@ 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
sales_channels list of strings Sales channels this discount is available on, such as
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
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.
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
@@ -95,6 +99,8 @@ 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,
@@ -151,6 +157,8 @@ 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,
@@ -193,6 +201,8 @@ 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,
@@ -224,6 +234,8 @@ 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,
@@ -284,6 +296,8 @@ 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,

View File

@@ -36,6 +36,8 @@ 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
@@ -47,8 +49,11 @@ 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.
sales_channels list A list of sales channels this event is available for
sale on.
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.
public_url string The public, customer-facing URL of the event (read-only).
===================================== ========================== =======================================================
@@ -129,11 +134,13 @@ Endpoints
"pretix.plugins.paypal",
"pretix.plugins.ticketoutputpdf"
],
"sales_channels": [
"all_sales_channels": false,
"limit_sales_channels": [
"web",
"pretixpos",
"resellers"
],
"sales_channels": [],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
}
]
@@ -223,6 +230,8 @@ Endpoints
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQTdBRDcvdkZBMzNFc1k0ejJQSHI3aVpQc1o4bjVkaDBhalA4Z3l6Tm1tSXM9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
]
},
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
@@ -280,11 +289,8 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"sales_channels": [
"web",
"pretixpos",
"resellers"
]
"all_sales_channels": true,
"limit_sales_channels": []
}
**Example response**:
@@ -320,6 +326,8 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
@@ -385,11 +393,8 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"sales_channels": [
"web",
"pretixpos",
"resellers"
]
"all_sales_channels": true,
"limit_sales_channels": []
}
**Example response**:
@@ -425,6 +430,8 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
@@ -500,6 +507,8 @@ Endpoints
"pretix.plugins.paypal",
"pretix.plugins.pretixdroid"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",

View File

@@ -96,6 +96,8 @@ 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.

View File

@@ -30,6 +30,7 @@ at :ref:`plugin-docs`.
checkinlists
waitinglist
customers
saleschannels
membershiptypes
memberships
giftcards
@@ -43,5 +44,7 @@ at :ref:`plugin-docs`.
scheduled_exports
shredders
sendmail_rules
auto_checkin_rules
billing_invoices
billing_var
billing_var
seats

View File

@@ -217,6 +217,9 @@ 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

View File

@@ -38,15 +38,26 @@ 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``
sales_channels list of strings Sales channels this variation is available on, such as
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
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``.
The item-level list takes precedence, i.e. a sales
channel needs to be on both lists for the item to be
available.
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.
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.
@@ -103,9 +114,13 @@ Endpoints
"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,9 +144,13 @@ Endpoints
"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,
@@ -145,6 +164,7 @@ 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 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
@@ -190,9 +210,13 @@ Endpoints
"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,
@@ -230,9 +254,12 @@ Endpoints
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"sales_channels": ["web"],
"all_sales_channels": false,
"limit_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,
@@ -261,9 +288,13 @@ Endpoints
"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,
@@ -323,9 +354,13 @@ Endpoints
"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,

View File

@@ -46,12 +46,23 @@ 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``).
sales_channels list of strings Sales channels this product is available on, such as
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
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.
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
set, this item won't be shown publicly as long as this
quota is available.
@@ -149,15 +160,26 @@ 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``.
├ sales_channels list of strings Sales channels this variation is available on, such as
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
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``.
The item-level list takes precedence, i.e. a sales
channel needs to be on both lists for the item to be
available.
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.
├ 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.
@@ -260,6 +282,8 @@ 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,
@@ -279,7 +303,9 @@ 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,
"require_voucher": false,
@@ -322,9 +348,13 @@ Endpoints
"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": {},
@@ -342,9 +372,13 @@ Endpoints
"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": {},
@@ -358,6 +392,7 @@ 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.
@@ -398,6 +433,8 @@ 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,
@@ -417,7 +454,9 @@ 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,
"require_voucher": false,
@@ -461,9 +500,13 @@ Endpoints
"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
@@ -480,9 +523,13 @@ Endpoints
"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": {},
@@ -517,7 +564,8 @@ Endpoints
"id": 1,
"name": {"en": "Standard ticket"},
"internal_name": "",
"sales_channels": ["web"],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"default_price": "23.00",
"original_price": null,
"category": null,
@@ -536,7 +584,9 @@ 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,
"require_voucher": false,
@@ -578,9 +628,12 @@ Endpoints
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"sales_channels": ["web"],
"all_sales_channels": false,
"limit_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": {},
@@ -598,9 +651,12 @@ Endpoints
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"sales_channels": ["web"],
"all_sales_channels": false,
"limit_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": {},
@@ -623,6 +679,8 @@ 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,
@@ -642,7 +700,9 @@ 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,
"require_voucher": false,
@@ -685,9 +745,13 @@ Endpoints
"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": {},
@@ -705,9 +769,13 @@ Endpoints
"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": {},
@@ -761,6 +829,8 @@ 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,
@@ -780,7 +850,9 @@ 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,
"require_voucher": false,
@@ -823,9 +895,13 @@ Endpoints
"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": {},
@@ -843,9 +919,13 @@ Endpoints
"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": {},

View File

@@ -42,6 +42,8 @@ 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
@@ -179,6 +181,11 @@ 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_rule integer The ID of the used tax rule (or ``null``)
@@ -210,6 +217,11 @@ 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
@@ -367,6 +379,7 @@ 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,
@@ -449,10 +462,13 @@ 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.
: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 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
@@ -548,6 +564,7 @@ Fetching individual orders
"fees": [],
"total": "23.00",
"comment": "",
"api_meta": {},
"custom_followup_at": null,
"checkin_attention": false,
"checkin_text": null,
@@ -589,6 +606,7 @@ Fetching individual orders
"country": "DE",
"state": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_rule": null,
"tax_value": "0.00",
@@ -727,6 +745,8 @@ Updating order fields
* ``comment``
* ``api_meta``
* ``custom_followup_at``
* ``invoice_address`` (you always need to supply the full object, or ``null`` to delete the current address)
@@ -1541,6 +1561,7 @@ 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",
@@ -1654,6 +1675,7 @@ Fetching individual positions
},
"attendee_email": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_rule": null,
"tax_value": "0.00",

View File

@@ -0,0 +1,219 @@
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",
"name": {
"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",
"name": {
"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",
"name": {
"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",
"name": {
"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",
"name": {
"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.

262
doc/api/resources/seats.rst Normal file
View File

@@ -0,0 +1,262 @@
.. _`rest-reusablemedia`:
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.

View File

@@ -1,6 +1,8 @@
Scheduled email rules
=====================
This feature requires the bundled ``pretix.plugins.sendmail`` plugin to be active for the event in order to work properly.
Resource description
--------------------
@@ -48,6 +50,7 @@ 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.

View File

@@ -22,6 +22,8 @@ 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
@@ -122,6 +124,7 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -159,6 +162,7 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -186,6 +190,7 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -203,6 +208,7 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -246,6 +252,7 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}

View File

@@ -41,6 +41,7 @@ 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``
@@ -115,6 +116,7 @@ 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

View File

@@ -12,8 +12,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_channels, register_global_settings, quota_availability, global_email_filter,
register_ticket_secret_generators, gift_card_transaction_display
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
Order events
""""""""""""
@@ -34,11 +35,11 @@ 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, 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
: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
.. automodule:: pretix.presale.signals
:members: order_info, order_info_top, order_meta_from_request
:members: order_info, order_info_top, order_meta_from_request, order_api_meta_from_request
Request flow
""""""""""""

View File

@@ -3,11 +3,12 @@
.. _`importcol`:
Extending the order import process
==================================
Extending the import process
============================
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.
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.
Import process
--------------
@@ -40,7 +41,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.orderimport.ImportColumn``
should listen for this signal and return the subclass of ``pretix.base.modelimport.ImportColumn``
that we'll provide in this plugin:
.. sourcecode:: python
@@ -56,10 +57,16 @@ that we'll provide in this plugin:
EmailColumn(sender),
]
Similar signals exist for other objects:
.. automodule:: pretix.base.signals
:members: voucher_import_columns
The column class API
--------------------
.. class:: pretix.base.orderimport.ImportColumn
.. class:: pretix.base.modelimport.ImportColumn
The central object of each import extension is the subclass of ``ImportColumn``.

View File

@@ -84,6 +84,8 @@ convenient to you:
.. automethod:: _register_fonts
.. automethod:: _register_event_fonts
.. automethod:: _on_first_page
.. automethod:: _on_other_page

View File

@@ -1,10 +1,11 @@
.. highlight:: python
:linenothreshold: 5
Writing an e-mail placeholder plugin
====================================
Writing a template placeholder plugin
=====================================
An email placeholder is a dynamic value that pretix users can use in their email templates.
A template placeholder is a dynamic value that pretix users can use in their email templates and in other
configurable texts.
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
@@ -12,31 +13,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 email placeholders. Your plugin
should listen for this signal and return an instance of a subclass of ``pretix.base.email.BaseMailTextPlaceholder``:
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``:
.. code-block:: python
from django.dispatch import receiver
from pretix.base.signals import register_mail_placeholders
from pretix.base.signals import register_text_placeholders
@receiver(register_mail_placeholders, dispatch_uid="placeholder_custom")
def register_mail_renderers(sender, **kwargs):
from .email import MyPlaceholderClass
@receiver(register_text_placeholders, dispatch_uid="placeholder_custom")
def register_placeholder_renderers(sender, **kwargs):
from .placeholders import MyPlaceholderClass
return MyPlaceholder()
Context mechanism
-----------------
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.
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.
Not all placeholders make sense in every email, and placeholders usually depend some parameters
Not all placeholders make sense everywhere, and placeholders usually depend on 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 an email if all those dependencies are
what values they depend on and they will only be available in a context where all those dependencies are
met. Currently, placeholders can depend on the following context parameters:
* ``event``
@@ -51,7 +52,7 @@ There are a few more that are only to be used internally but not by plugins.
The placeholder class
---------------------
.. class:: pretix.base.email.BaseMailTextPlaceholder
.. class:: pretix.base.services.placeholders.BaseTextPlaceholder
.. autoattribute:: identifier
@@ -77,7 +78,15 @@ functions:
.. code-block:: python
placeholder = SimpleFunctionalMailTextPlaceholder(
placeholder = SimpleFunctionalTextPlaceholder(
'code', ['order'], lambda order: order.code, sample='F8VVL'
)
Signals
-------
.. automodule:: pretix.base.signals
:members: register_text_placeholders
.. automodule:: pretix.base.signals
:members: register_mail_placeholders

View File

@@ -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**

View File

@@ -19,3 +19,4 @@ Contents:
permissions
logging
locking
timemachine

View File

@@ -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
* References to Django ``File`` objects that are already stored in a storage backend [#f1]_
* 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,6 +55,9 @@ You can simply use it like this:
"preserve his reservation."),
)
.. _settings-defaults-in-plugins:
Defaults in plugins
-------------------
@@ -70,3 +73,9 @@ 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.

View File

@@ -0,0 +1,32 @@
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

View File

@@ -90,6 +90,10 @@ as its first argument and can be used like this::
<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
----------------------

View File

@@ -136,9 +136,7 @@ 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
@@ -211,5 +209,15 @@ 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

View File

@@ -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.

View File

@@ -34,13 +34,19 @@ 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.
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:
@@ -62,6 +68,7 @@ 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
@@ -105,13 +112,17 @@ 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",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": ""
"comment": "",
"exhibitor_tags": []
}
]
}
@@ -156,13 +167,17 @@ 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",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": ""
"comment": "",
"exhibitor_tags": []
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -357,12 +372,16 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": ""
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
}
**Example response**:
@@ -386,13 +405,19 @@ 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",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": ""
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
}
:param organizer: The ``slug`` field of the organizer to create new exhibitor for
@@ -444,13 +469,19 @@ 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",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": ""
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
}
:param organizer: The ``slug`` field of the organizer to modify
@@ -561,6 +592,7 @@ 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.
@@ -596,6 +628,7 @@ 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,
@@ -634,6 +667,7 @@ 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
@@ -668,7 +702,8 @@ The request for this looks like this:
"scan_type": "lead",
"tags": ["foo"],
"rating": 4,
"device_name": "DEV1"
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
}
**Example response:**
@@ -701,7 +736,9 @@ The request for this looks like this:
},
"rating": 4,
"tags": ["foo"],
"notes": "Great customer, wants our newsletter"
"notes": "Great customer, wants our newsletter",
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
}
:statuscode 200: No error, leads was not scanned for the first time
@@ -756,7 +793,9 @@ You can also fetch existing leads (if you are authorized to do so):
},
"rating": 4,
"tags": ["foo"],
"notes": "Great customer, wants our newsletter"
"notes": "Great customer, wants our newsletter",
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
}
]
}

View File

@@ -0,0 +1,105 @@
GetYourGuide
============
.. note::
The GetYourGuide integration is currently in Beta. Please contact support@pretix.eu to enable the integration
for your pretix.eu organizer account.
Introduction
------------
Using third party aggregators, such als GetYourGuide, event organizers can sell tickets to their events not only on
their own ticket-shop but also on the aggregator's portal. While this service is not for free, it allows event
organizers to reacher a larger audience that would otherwise not have found their way into the organizers webshop.
Using pretix' integration with GetYourGuide, event organizers can profit from an additional sales and revenue channel,
while keeping the effort for setting up and maintaining multiple ticket shops to a minimum.
Preparing your organizer account
--------------------------------
The first step in enabling the GetYourGuide integration, is to setup a corresponding Sales Channel, which will be used
to properly attribute the sales generated. This needs to be done only once per organizer account.
To do so, log into the pretix backend, select ``Organizers`` from the navigation and then the organizer in question.
Extending the ``Settings``-menu, find the ``Sales channels`` configuration and click the ``Add a new channel`` button.
On the following page, you will be able to select ``GetYourGuide`` as the sales channel type and give it a custom name.
Preparing your event
--------------------
In order to now sell your events on GetYourGuide, you will need to configure each event in question.
1. Enabling the plugin
Within your event, extend the ``Settings`` menu and navigate to ``Plugins``. Activate the plugin in the
``Integrations`` tab.
2. Sell the event on the sales channel
Pick the sales channel or channels, on which you would like to sell your event by navigating to the event's general
settings page using the ``Sell on all sales channels`` or ``Restrict to specific sales channels`` checkboxes.
3. Configure one or more products to be sold on GetYourGuide
Either create a new or edit an existing product, that you would like to sell on GetYourGuide. To do so, you will
need to have checked the ``Sell on all sales channels`` or appropriate ``Restrict to specific sales channels``
checkbox of the product within it's ``Availability`` tab.
In addition, you will also need to set the GetYourGuide equivalent ticket category in the product's accordingly
named settings tab. Within your event, there can be only one product per ticket category. Depending on your further
configuration, you must at least select one product to be in the ``Adult`` or ``Group`` category.
4. Configuring the GetYourGuide-plugin
Once you have configured one or more products to be eligible to be sold on GetYourGuide, you'll need to configure a
few basic settings within the event (``Settings`` --> ``GetYourGuide``). The most important settings can be found
the in the ``Configuration`` tab, such as the location of the event on sale.
Ticket Categories
-----------------
While pretix only uses the ticket category term loosely to group together multiple products for nicer display,
GetYourGuide is relying on the ticket categories to price the tickets.
First of all, you need to make the decision on how you are planning on selling your tickets on GetYourGuide - in most
cases, this will reflect your current sales strategy within your pretix shop.
- Individual tickets
Every single person attending will need to purchase their own ticket. A family of two adults and two
children will have to purchase and pay for a total of 4 tickets.
In this case, you will need to offer *at least* a ticket of the ``Adult`` type, but may offer any other ticket
category type (Child, Youth, Senior, ...) in addition. But you cannot offer a ``Group`` ticket.
- Group tickets
Two groups, consisting of 10 and 20 participants respectively, won't need to purchase a total of 30 tickets, but
rather two group tickets. It is up to you to configure the group size limits within the GetYourGuide-settings of your
product.
Choosing this option, you cannot offer any other ticket categories besides ``Group``.
Setting up event dates and quotas
---------------------------------
Of course, in addition to creating products, you will also need to add them to a quota for them to be available for
sale. The process for doing this is the very same as for any regular event or event series.
.. note::
When selling individual tickets through GetYourGuide, you will not be able to offer differing quantities for
individual ticket categories.
For this reason, we recommend to place all GetYourGuide-eligible products into the same quota. Should you however opt
to create multiple quotas which create an imbalance, pretix will report only the available number of tickets for the
lowest relevant quota.
Connecting your event to GetYourGuide
-------------------------------------
Once you have set up your event and products and performed all necessary configuration, you may want to use the
Analyzer-feature of our GetYourGuide-plugin (``Settings`` -> ``GetYourGuide`` -> tab ``Analyzer``).
The Analyzer should not display any blocking error messages and at least one event date that is ready for publishing on
the GetYourGuide platform.
At this point, you will need to setup your event (called ``product`` in the GetYourGuide universe) on their
`Supplier Portal`_ and connect it with your pretix shop. To do so, please follow the
`Connecting a new product to your Reservation System`_ on the GetYourGuide Supply Partner Help Center.
Select ``pretix.eu`` as your reservation system; the required ``product ID`` can be found in the ``Configuration`` tab
of the GetYourGuide plugin settings page.
From this point on, GetYourGuide will automatically import the availabilities and products and offer them for sale.
.. _Supplier Portal: https://suppliers.getyourguide.com/
.. _Connecting a new product to your Reservation System: https://supply.getyourguide.support/hc/en-us/articles/18008029689373-Connecting-a-new-product-to-your-Reservation-system

View File

@@ -25,3 +25,4 @@ If you want to **create** a plugin, please go to the
webinar
presale-saml
kulturpass
getyourguide

View File

@@ -1,4 +1,4 @@
sphinx==7.0.*
sphinx==7.4.*
jinja2==3.1.*
sphinx-rtd-theme
sphinxcontrib-httpdomain
@@ -6,5 +6,4 @@ sphinxcontrib-images
sphinxcontrib-jquery
sphinxcontrib-spelling==8.*
sphinxemoji
pygments-markdown-lexer
pyenchant==3.2.*

View File

@@ -1,5 +1,5 @@
-e ../
sphinx==7.0.*
sphinx==7.4.*
jinja2==3.1.*
sphinx-rtd-theme
sphinxcontrib-httpdomain
@@ -7,5 +7,4 @@ sphinxcontrib-images
sphinxcontrib-jquery
sphinxcontrib-spelling==8.*
sphinxemoji
pygments-markdown-lexer
pyenchant==3.2.*

View File

@@ -0,0 +1,110 @@
Android version support policy
==============================
Building software for Android always presents a struggle between keeping compatibility with older hardware to save cost
and utilizing feature of new Android versions to improve functionality, security and stability. To help you plan ahead,
we are publishing our intended schedule. This is to be understood as a minimum commitment, we will only drop support for
older versions if there is a technical reason to do so, not because the scheduled time has been reached.
.. warning:: This is a non-binding document. We will try our very best to not to deprecate support for Android versions
earlier than listed here, but for technical or economical reasons, it might become necessary to do so under
specific circumstances. Specifically, we might be forced to partially drop support for Android versions
earlier where we integrate third-party components into our software. Typical examples would be specific
payment terminal or printer types where we use a third-party component provided by the hardware vendor.
If we no longer support an Android version, it means that we will no longer publish new versions of the app supporting
that Android version. This means you are not getting new features or bug fixes, and at some point your app might stop
working with the pretix server.
pretixSCAN
----------
=========================== ==========================================================
Android Version Support schedule
=========================== ==========================================================
Android 14 Support planned until at least 12/2029.
Android 13 Support planned until at least 12/2028.
Android 12 Support planned until at least 12/2027.
Android 11 Support planned until at least 12/2026.
Android 10 Support planned until at least 12/2025.
Android 9 Support planned until at least 12/2025.
Android 8 Support planned until at least 12/2025.
Android 7 Support planned until at least 06/2025.
Android 6 Support planned until at least 06/2025.
Android 5 Support planned until at least 06/2025.
Android 4 Support dropped.
=========================== ==========================================================
pretixPOS
---------
=========================== ==========================================================
Android Version Support schedule
=========================== ==========================================================
Android 14 | Support planned until at least 12/2029.
| Limited support for Swissbit microSD TSE (only tested devices).
Android 13 | Support planned until at least 12/2028.
| Limited support for Swissbit microSD TSE (only tested devices).
Android 12 | Support planned until at least 12/2027.
| Limited support for Swissbit microSD TSE (only tested devices).
Android 11 | Support planned until at least 12/2026.
| No support for Swissbit microSD TSE.
Android 10 Support planned until at least 12/2025.
Android 9 Support planned until at least 12/2025.
Android 8 | Support planned until at least 12/2025.
| Support for Stripe Terminal on some devices to be dropped 05/2024.
Android 7 | Support planned until at least 12/2024.
| Support for Stripe Terminal to be dropped 05/2024.
| No support for Cryptovision TSE.
| No support for SumUp.
Android 6 | Support planned until at least 12/2024.
| No support for Cryptovision TSE.
| No support for Fiskal Cloud.
| No support for Stripe Terminal.
| No support for SumUp.
Android 5 | Support planned until at least 12/2024.
| No support for Cryptovision TSE.
| No support for Fiskal Cloud.
| No support for Stripe Terminal.
| No support for SumUp.
Android 4 Support dropped.
=========================== ==========================================================
pretixPRINT
-----------
=========================== ==========================================================
Android Version Support schedule
=========================== ==========================================================
Android 14 Support planned until at least 12/2029.
Android 13 Support planned until at least 12/2028.
Android 12 Support planned until at least 12/2027.
Android 11 Support planned until at least 12/2026.
Android 10 Support planned until at least 12/2025.
Android 9 Support planned until at least 12/2025.
Android 8 Support planned until at least 12/2025.
Android 7 Support planned until at least 06/2025.
Android 6 Support planned until at least 06/2025.
Android 5 | Support planned until at least 06/2025.
| No support for Evolis printers on some devices.
Android 4 Support dropped.
=========================== ==========================================================
pretixLEAD
----------
=========================== ==========================================================
Android Version Support schedule
=========================== ==========================================================
Android 14 Support planned until at least 12/2029.
Android 13 Support planned until at least 12/2028.
Android 12 Support planned until at least 12/2027.
Android 11 Support planned until at least 12/2026.
Android 10 Support planned until at least 12/2025.
Android 9 Support planned until at least 12/2025.
Android 8 Support planned until at least 12/2025.
Android 7 Support planned until at least 12/2024.
Android 6 Support planned until at least 12/2024.
Android 5 Support planned until at least 12/2024.
Android 4 Support dropped.
=========================== ==========================================================

View File

@@ -19,4 +19,3 @@ Then, head to the **Bundled products** tab of the "conference ticket" and add th
Once a customer tries to buy the € 450 conference ticket, a sub-product will be added and the price will automatically be split into the two components, leading to a correct computation of taxes.
You can find more use cases in these specialized guides:

View File

@@ -17,8 +17,8 @@ and then click "Generate widget code".
You will obtain two code snippets that look *roughly* like the following. The first should be embedded into the
``<head>`` part of your website, if possible. If this inconvenient, you can put it in the ``<body>`` part as well::
<link rel="stylesheet" type="text/css" href="https://pretix.eu/demo/democon/widget/v1.css">
<script type="text/javascript" src="https://pretix.eu/widget/v1.en.js" async></script>
<link rel="stylesheet" type="text/css" href="https://pretix.eu/demo/democon/widget/v1.css" crossorigin>
<script type="text/javascript" src="https://pretix.eu/widget/v1.en.js" async crossorigin></script>
The second snippet should be embedded at the position where the widget should show up::
@@ -339,9 +339,9 @@ Currently, the following attributes are understood by pretix itself:
``data-attendee-name``, which will pre-fill the last part of the name, whatever that is.
* ``data-invoice-address-FIELD`` will pre-fill the corresponding field of the invoice address. Possible values for
``FIELD`` are ``company``, ``street``, ``zipcode``, ``city`` and ``country``, as well as fields specified by the
naming scheme such as ``name-title`` or ``name-given-name`` (see above). ``country`` expects a two-character
country code.
``FIELD`` are ``company``, ``street``, ``zipcode``, ``city``, ``country``, ``internal-reference``, ``vat-id``, and
``custom-field``, as well as fields specified by the naming scheme such as ``name-title`` or ``name-given-name``
(see above). ``country`` expects a two-character country code.
* If ``data-fix="true"`` is given, the user will not be able to change the other given values later. This currently
only works for the order email address as well as the invoice address. Attendee-level fields and questions can
@@ -429,4 +429,57 @@ Hosted or pretix Enterprise are active, you can pass the following fields:
});
</script>
Offering wallet payments (Apple Pay, Google Pay) within the widget
------------------------------------------------------------------
Some payment providers (such as Stripe) also offer Apple or Google Pay. But in order to use them, the domain of the
payment needs to be approved first. As of right now, pretix will take care of the domain verification process for you
automatically, when using Stripe. However, pretix can only validate the domain that is being used for your default,
"stand-alone" shop (such as https://pretix.eu/demo/democon/ ).
When embedding the widget on your website, the domain of the embedding page will also need to be validated in order to
be able to use it for wallet payments.
The details might vary from payment provider to payment provider, but generally speaking, it will either involve just
telling your payment provider the domain name and (for Apple Pay) placing an
``apple-developer-merchantid-domain-association``-file into the ``.well-known``-directory of your domain.
Further reading:
* `Stripe Payment Method Domain registration`_
Content Security Policy
-----------------------
When using a Content Security Policy (CSP) on your website, you may need to make some adjustments. If your pretix
shop is running under a custom domain, you need to add the following rules:
* ``script-src``: ``'unsafe-eval' https://pretix.eu`` (adjust to your domain for self-hosted pretix)
* ``style-src``: ``https://pretix.eu`` (adjust to your domain for self-hosted pretix **and** for custom domain on pretix Hosted)
* ``connect-src``: ``https://pretix.eu`` (adjust to your domain for self-hosted pretix **and** for custom domain on pretix Hosted)
* ``frame-src``: ``https://pretix.eu`` (adjust to your domain for self-hosted pretix **and** for custom domain on pretix Hosted)
* ``img-src``: ``https://pretix.eu`` (adjust to your domain for self-hosted pretix **and** for custom domain on pretix Hosted) and for pretix Hosted additionally add ``https://cdn.pretix.space``
External payment providers and Cross-Origin-Opener-Policy
---------------------------------------------------------
If you use a payment provider that opens a new window during checkout (such as PayPal), be aware that setting
``Cross-Origin-Opener-Policy: same-origin`` results in an empty popup-window being opened in the foreground. This is
due to JavaScript not having access to the opened window. To mitigate this, you either need to always open the widgets
checkout in a new tab (see :ref:`Always open a new tab`) or set ``Cross-Origin-Opener-Policy: same-origin-allow-popups``
Working with Cross-Origin-Embedder-Policy
-----------------------------------------
The pretix widget is unfortunately not compatible with ``Cross-Origin-Embedder-Policy: require-corp``. If you include
the ``crossorigin`` attributes on the ``<script>`` and ``<link>`` tag as shown above, the widget can show a calendar
or product list, but will not be able to open the checkout process in an iframe. If you also set
``Cross-Origin-Opener-Policy: same-origin``, the widget can auto-detect that it is running in an isolated enviroment
and will instead open the checkout process in a new tab.
.. _Let's Encrypt: https://letsencrypt.org/
.. _Stripe Payment Method Domain registration: https://stripe.com/docs/payments/payment-methods/pmd-registration

View File

@@ -16,4 +16,5 @@ wanting to use pretix to sell tickets.
events/giftcards
faq
markdown
android-version-support
glossary

View File

@@ -11,6 +11,9 @@ In many places of your shop, like frontpage texts, product descriptions and emai
since it is way easier to learn than languages like HTML but allows all basic formatting options required
for text in those places.
.. note:: Some fields that are used in one-line context only allow formatting that refers to individual words
(such as bold or italic font or a link) but do not allow block-level formatting like lists or headlines.
Formatting rules
----------------

View File

@@ -22,7 +22,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
]
dependencies = [
@@ -30,42 +30,41 @@ dependencies = [
"babel",
"BeautifulSoup4==4.12.*",
"bleach==5.0.*",
"celery==5.3.*",
"chardet==5.1.*",
"celery==5.4.*",
"chardet==5.2.*",
"cryptography>=3.4.2",
"css-inline==0.8.*",
"css-inline==0.14.*",
"defusedcsv>=1.1.0",
"dj-static",
"Django==4.2.*",
"django-bootstrap3==23.1.*",
"django-compressor==4.3.*",
"django-countries==7.5.*",
"django-filter==23.2",
"Django[argon2]==4.2.*,>=4.2.15",
"django-bootstrap3==24.2",
"django-compressor==4.5.1",
"django-countries==7.6.*",
"django-filter==24.3",
"django-formset-js-improved==0.5.0.3",
"django-formtools==2.4.1",
"django-hierarkey==1.1.*",
"django-hijack==3.3.*",
"django-formtools==2.5.1",
"django-hierarkey==1.2.*",
"django-hijack==3.6.*",
"django-i18nfield==1.9.*,>=1.9.4",
"django-libsass==0.9",
"django-localflavor==4.0",
"django-markup",
"django-oauth-toolkit==2.2.*",
"django-otp==1.2.*",
"django-phonenumber-field==7.1.*",
"django-redis==5.2.*",
"django-oauth-toolkit==2.3.*",
"django-otp==1.5.*",
"django-phonenumber-field==7.3.*",
"django-redis==5.4.*",
"django-scopes==2.0.*",
"django-statici18n==2.3.*",
"djangorestframework==3.14.*",
"dnspython==2.3.*",
"django-statici18n==2.5.*",
"djangorestframework==3.15.*",
"dnspython==2.6.*",
"drf_ujson2==1.7.*",
"geoip2==4.*",
"importlib_metadata==7.*", # Polyfill, we can probably drop this once we require Python 3.10+
"importlib_metadata==8.*", # Polyfill, we can probably drop this once we require Python 3.10+
"isoweek",
"jsonschema",
"kombu==5.3.*",
"libsass==0.22.*",
"kombu==5.4.*",
"libsass==0.23.*",
"lxml",
"markdown==3.4.3", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
"markdown==3.7", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
# We can upgrade markdown again once django-bootstrap3 upgrades or once we drop Python 3.6 and 3.7
"mt-940==4.30.*",
"oauthlib==3.2.*",
@@ -73,63 +72,60 @@ dependencies = [
"packaging",
"paypalrestsdk==1.13.*",
"paypal-checkout-serversdk==1.0.*",
"PyJWT==2.7.*",
"PyJWT==2.9.*",
"phonenumberslite==8.13.*",
"Pillow==9.5.*",
"Pillow==10.4.*",
"pretix-plugin-build",
"protobuf==4.23.*",
"protobuf==5.27.*",
"psycopg2-binary",
"pycountry",
"pycparser==2.21",
"pycryptodome==3.18.*",
"pypdf==3.9.*",
"python-bidi==0.4.*", # Support for Arabic in reportlab
"python-dateutil==2.8.*",
"python-u2flib-server==4.*",
"pycparser==2.22",
"pycryptodome==3.20.*",
"pypdf==4.3.*",
"python-bidi==0.6.*", # Support for Arabic in reportlab
"python-dateutil==2.9.*",
"pytz",
"pytz-deprecation-shim==0.1.*",
"pyuca",
"qrcode==7.4.*",
"redis==4.6.*",
"reportlab==4.0.*",
"redis==5.0.*",
"reportlab==4.2.*",
"requests==2.31.*",
"sentry-sdk==1.15.*",
"sentry-sdk==2.13.*",
"sepaxml==2.6.*",
"slimit",
"static3==0.7.*",
"stripe==7.9.*",
"text-unidecode==1.*",
"tlds>=2020041600",
"tqdm==4.*",
"ua-parser==0.18.*",
"vat_moss_forked==2020.3.20.0.11.0",
"vobject==0.9.*",
"webauthn==0.4.*",
"webauthn==2.2.*",
"zeep==4.2.*"
]
[project.optional-dependencies]
memcached = ["pylibmc"]
dev = [
"aiohttp==3.8.*",
"aiohttp==3.10.*",
"coverage",
"coveralls",
"fakeredis==2.18.*",
"flake8==6.0.*",
"fakeredis==2.23.*",
"flake8==7.1.*",
"freezegun",
"isort==5.12.*",
"pep8-naming==0.13.*",
"isort==5.13.*",
"pep8-naming==0.14.*",
"potypo",
"pycodestyle==2.10.*",
"pyflakes==3.0.*",
"pytest-asyncio",
"pytest-cache",
"pytest-cov",
"pytest-django==4.*",
"pytest-mock==3.10.*",
"pytest-rerunfailures==11.*",
"pytest-mock==3.14.*",
"pytest-rerunfailures==14.*",
"pytest-sugar",
"pytest-xdist==3.3.*",
"pytest==7.3.*",
"pytest-xdist==3.6.*",
"pytest==8.3.*",
"responses",
]

4
src/.watchmanconfig Normal file
View File

@@ -0,0 +1,4 @@
{
"ignore_dirs": ["node_modules", "data", "pretix/static", "pretix/locale", "pretix/static.dist"]
}

View File

@@ -6,7 +6,7 @@ localecompile:
./manage.py compilemessages
localegen:
./manage.py makemessages --keep-pot --ignore "pretix/helpers/*" --ignore "pretix/static/npm_dir/*" $(LNGS)
./manage.py makemessages --keep-pot --ignore "pretix/static/npm_dir/*" $(LNGS)
./manage.py makemessages --keep-pot -d djangojs --ignore "pretix/static/npm_dir/*" --ignore "pretix/helpers/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static.dist/*" --ignore "data/*" --ignore "pretix/static/rrule/*" --ignore "build/*" $(LNGS)
staticfiles: jsi18n

View File

@@ -19,4 +19,4 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
__version__ = "2023.11.0.dev0"
__version__ = "2024.8.0.dev0"

View File

@@ -62,6 +62,7 @@ INSTALLED_APPS = [
'pretix.plugins.badges',
'pretix.plugins.manualpayment',
'pretix.plugins.returnurl',
'pretix.plugins.autocheckin',
'pretix.plugins.webcheckin',
'django_countries',
'oauth2_provider',
@@ -79,6 +80,7 @@ ALL_LANGUAGES = [
('de', _('German')),
('de-informal', _('German (informal)')),
('ar', _('Arabic')),
('ca', _('Catalan')),
('zh-hans', _('Chinese (simplified)')),
('zh-hant', _('Chinese (traditional)')),
('cs', _('Czech')),
@@ -98,6 +100,8 @@ ALL_LANGUAGES = [
('pt-br', _('Portuguese (Brazil)')),
('ro', _('Romanian')),
('ru', _('Russian')),
('sk', _('Slovak')),
('sv', _('Swedish')),
('es', _('Spanish')),
('tr', _('Turkish')),
('uk', _('Ukrainian')),
@@ -111,6 +115,7 @@ LANGUAGES_RTL = {
LANGUAGES_INCUBATING = {
'fi', 'pt-br', 'gl',
}
LANGUAGES = ALL_LANGUAGES
LOCALE_PATHS = [
os.path.join(os.path.dirname(__file__), 'locale'),
]
@@ -234,7 +239,12 @@ COMPRESS_FILTERS = {
)
}
CURRENCIES = list(currencies)
CURRENCIES = [
c for c in currencies
if c.alpha_3 not in {
'XAG', 'XAU', 'XBA', 'XBB', 'XBC', 'XBD', 'XDR', 'XPD', 'XPT', 'XSU', 'XTS', 'XUA',
}
]
CURRENCY_PLACES = {
# default is 2
'BIF': 0,

View File

@@ -19,6 +19,8 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import logging
from django.contrib.auth.models import AnonymousUser
from django_scopes import scopes_disabled
from rest_framework import exceptions
@@ -29,6 +31,8 @@ from pretix.api.auth.devicesecurity import (
)
from pretix.base.models import Device
logger = logging.getLogger(__name__)
class DeviceTokenAuthentication(TokenAuthentication):
model = Device
@@ -46,6 +50,7 @@ class DeviceTokenAuthentication(TokenAuthentication):
raise exceptions.AuthenticationFailed('Device has not been initialized.')
if device.revoked:
logging.warning(f'Connection attempt of revoked device {device.pk}.')
raise exceptions.AuthenticationFailed('Device access has been revoked.')
return AnonymousUser(), device

View File

@@ -185,6 +185,7 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
('GET', 'api-v1:order-detail'),
('DELETE', 'api-v1:orderposition-detail'),
('PATCH', 'api-v1:orderposition-detail'),
('GET', 'api-v1:orderposition-list'),
('GET', 'api-v1:orderposition-answer'),
('GET', 'api-v1:orderposition-pdf_image'),
('POST', 'api-v1:order-mark-canceled'),
@@ -223,6 +224,7 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
('POST', 'api-v1:checkinrpc.redeem'),
('GET', 'api-v1:checkinrpc.search'),
('POST', 'api-v1:reusablemedium-lookup'),
('GET', 'api-v1:reusablemedium-list'),
('POST', 'api-v1:reusablemedium-list'),
)

View File

@@ -39,7 +39,8 @@ from pretix.base.models import Device, Event, User
from pretix.base.models.auth import SuperuserPermissionSet
from pretix.base.models.organizer import TeamAPIToken
from pretix.helpers.security import (
SessionInvalid, SessionReauthRequired, assert_session_valid,
Session2FASetupRequired, SessionInvalid, SessionPasswordChangeRequired,
SessionReauthRequired, assert_session_valid,
)
@@ -66,6 +67,10 @@ class EventPermission(BasePermission):
return False
except SessionReauthRequired:
return False
except Session2FASetupRequired:
return False
except SessionPasswordChangeRequired:
return False
perm_holder = (request.auth if isinstance(request.auth, (Device, TeamAPIToken))
else request.user)
@@ -144,6 +149,10 @@ class ProfilePermission(BasePermission):
return False
except SessionReauthRequired:
return False
except Session2FASetupRequired:
return False
except SessionPasswordChangeRequired:
return False
if isinstance(request.auth, OAuthAccessToken):
if not (request.auth.allow_scopes(['read']) or request.auth.allow_scopes(['profile'])) and request.method in SAFE_METHODS:
@@ -166,5 +175,9 @@ class AnyAuthenticatedClientPermission(BasePermission):
return False
except SessionReauthRequired:
return False
except Session2FASetupRequired:
return False
except SessionPasswordChangeRequired:
return False
return True

View File

@@ -0,0 +1,49 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from rest_framework import exceptions
from rest_framework.authentication import (
SessionAuthentication as BaseSessionAuthentication,
)
from pretix.multidomain.middlewares import CsrfViewMiddleware
class CustomCSRFCheck(CsrfViewMiddleware):
def _reject(self, request, reason):
# Return the failure reason instead of an HttpResponse
return reason
class SessionAuthentication(BaseSessionAuthentication):
# Override from DRF to user our custom CSRF middleware
def enforce_csrf(self, request):
def dummy_get_response(request): # pragma: no cover
return None
check = CustomCSRFCheck(dummy_get_response)
# populates request.META['CSRF_COOKIE'], which is used in process_view()
check.process_request(request)
reason = check.process_view(request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)

82
src/pretix/api/filters.py Normal file
View File

@@ -0,0 +1,82 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from django import forms
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.models.constants import LOOKUP_SEP
from django.forms import MultipleChoiceField
from django_filters import Filter
from django_filters.conf import settings
class MultipleCharField(forms.CharField):
widget = forms.MultipleHiddenInput
def to_python(self, value):
if not value:
return []
elif not isinstance(value, (list, tuple)):
raise ValidationError(
MultipleChoiceField.default_error_messages["invalid_list"], code="invalid_list"
)
return [str(val) for val in value]
class MultipleCharFilter(Filter):
"""
This filter performs OR(by default) or AND(using conjoined=True) query
on the selected inputs.
"""
field_class = MultipleCharField
def __init__(self, *args, **kwargs):
self.conjoined = kwargs.pop("conjoined", False)
super().__init__(*args, **kwargs)
def filter(self, qs, value):
if not value:
# Even though not a noop, no point filtering if empty.
return qs
if not self.conjoined:
q = Q()
for v in set(value):
predicate = self.get_filter_predicate(v)
if self.conjoined:
qs = self.get_method(qs)(**predicate)
else:
q |= Q(**predicate)
if not self.conjoined:
qs = self.get_method(qs)(q)
return qs.distinct() if self.distinct else qs
def get_filter_predicate(self, v):
name = self.field_name
if name and self.lookup_expr != settings.DEFAULT_LOOKUP_EXPR:
name = LOOKUP_SEP.join([name, self.lookup_expr])
try:
return {name: getattr(v, self.field.to_field_name)}
except (AttributeError, TypeError):
return {name: v}

View File

@@ -54,7 +54,7 @@ class IdempotencyMiddleware:
auth_hash_parts = '{}:{}'.format(
request.headers.get('Authorization', ''),
request.COOKIES.get(settings.SESSION_COOKIE_NAME, '')
request.COOKIES.get('__Host-' + settings.SESSION_COOKIE_NAME, request.COOKIES.get(settings.SESSION_COOKIE_NAME, ''))
)
auth_hash = sha1(auth_hash_parts.encode()).hexdigest()
idempotency_key = request.headers.get('X-Idempotency-Key', '')

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.2.10 on 2024-02-12 11:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pretixapi", "0011_bigint"),
]
operations = [
migrations.AddField(
model_name="oauthapplication",
name="post_logout_redirect_uris",
field=models.TextField(default=""),
),
]

View File

@@ -42,6 +42,11 @@ class OAuthApplication(AbstractApplication):
verbose_name=_("Redirection URIs"),
help_text=_("Allowed URIs list, space separated")
)
post_logout_redirect_uris = models.TextField(
blank=True, validators=[URIValidator],
help_text=_("Allowed Post Logout URIs list, space separated"),
default="",
)
client_id = models.CharField(
verbose_name=_("Client ID"),
max_length=100, unique=True, default=generate_client_id, db_index=True

View File

@@ -21,7 +21,9 @@
#
import json
from django.db.models import prefetch_related_objects
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
class AsymmetricField(serializers.Field):
@@ -61,3 +63,59 @@ class CompatibleJSONField(serializers.JSONField):
if value:
return json.loads(value)
return value
class SalesChannelMigrationMixin:
"""
Translates between the old field "sales_channels" and the new field combo "all_sales_channels"/"limit_sales_channels".
"""
@property
def organizer(self):
if "organizer" in self.context:
return self.context["organizer"]
elif "event" in self.context:
return self.context["event"].organizer
else:
raise ValueError("organizer not in context")
def to_internal_value(self, data):
if "sales_channels" in data:
prefetch_related_objects([self.organizer], "sales_channels")
all_channels = {
s.identifier for s in
self.organizer.sales_channels.all()
}
if data.get("all_sales_channels") and set(data["sales_channels"]) != all_channels:
raise ValidationError(
"If 'all_sales_channels' is set, the legacy attribute 'sales_channels' must not be set or set to "
"the list of all sales channels."
)
if data.get("limit_sales_channels") and set(data["sales_channels"]) != set(data["limit_sales_channels"]):
raise ValidationError(
"If 'limit_sales_channels' is set, the legacy attribute 'sales_channels' must not be set or set to "
"the same list."
)
if data["sales_channels"] == all_channels:
data["all_sales_channels"] = True
data["limit_sales_channels"] = []
else:
data["all_sales_channels"] = False
data["limit_sales_channels"] = data["sales_channels"]
del data["sales_channels"]
return super().to_internal_value(data)
def to_representation(self, value):
value = super().to_representation(value)
if value.get("all_sales_channels"):
prefetch_related_objects([self.organizer], "sales_channels")
value["sales_channels"] = sorted([
s.identifier for s in
self.organizer.sales_channels.all()
])
else:
value["sales_channels"] = value["limit_sales_channels"]
return value

View File

@@ -33,7 +33,7 @@ from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.order import (
AnswerCreateSerializer, AnswerSerializer, InlineSeatSerializer,
)
from pretix.base.models import Seat, Voucher
from pretix.base.models import SalesChannel, Seat, Voucher
from pretix.base.models.orders import CartPosition
@@ -212,7 +212,11 @@ class CartPositionCreateSerializer(BaseCartPositionCreateSerializer):
addons = BaseCartPositionCreateSerializer(many=True, required=False)
bundled = BaseCartPositionCreateSerializer(many=True, required=False)
seat = serializers.CharField(required=False, allow_null=True)
sales_channel = serializers.CharField(required=False, default='sales_channel')
sales_channel = serializers.SlugRelatedField(
slug_field='identifier',
queryset=SalesChannel.objects.none(),
required=False,
)
voucher = serializers.CharField(required=False, allow_null=True)
class Meta:
@@ -221,6 +225,10 @@ class CartPositionCreateSerializer(BaseCartPositionCreateSerializer):
'cart_id', 'expires', 'addons', 'bundled', 'seat', 'sales_channel', 'voucher'
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["sales_channel"].queryset = self.context["event"].organizer.sales_channels.all()
def validate_cart_id(self, cid):
if cid and not cid.endswith('@api'):
raise ValidationError('Cart ID should end in @api or be empty.')

View File

@@ -25,14 +25,20 @@ from rest_framework.exceptions import ValidationError
from pretix.api.serializers.event import SubEventSerializer
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.base.channels import get_all_sales_channels
from pretix.base.media import MEDIA_TYPES
from pretix.base.models import Checkin, CheckinList
from pretix.base.models import Checkin, CheckinList, SalesChannel
class CheckinListSerializer(I18nAwareModelSerializer):
checkin_count = serializers.IntegerField(read_only=True)
position_count = serializers.IntegerField(read_only=True)
auto_checkin_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = CheckinList
@@ -43,6 +49,8 @@ class CheckinListSerializer(I18nAwareModelSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['auto_checkin_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
if 'subevent' in self.context['request'].query_params.getlist('expand'):
self.fields['subevent'] = SubEventSerializer(read_only=True)
@@ -72,10 +80,6 @@ class CheckinListSerializer(I18nAwareModelSerializer):
if full_data.get('subevent'):
raise ValidationError(_('The subevent does not belong to this event.'))
for channel in full_data.get('auto_checkin_sales_channels') or []:
if channel not in get_all_sales_channels():
raise ValidationError(_('Unknown sales channel.'))
CheckinList.validate_rules(data.get('rules'))
return data

View File

@@ -19,18 +19,27 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from rest_framework import serializers
from pretix.api.serializers import SalesChannelMigrationMixin
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.base.models import Discount
from pretix.base.models import Discount, SalesChannel
class DiscountSerializer(I18nAwareModelSerializer):
class DiscountSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
limit_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = Discount
fields = ('id', 'active', 'internal_name', 'position', 'sales_channels', 'available_from',
'available_until', 'subevent_mode', 'condition_all_products', 'condition_limit_products',
'condition_apply_to_addons', 'condition_min_count', 'condition_min_value',
fields = ('id', 'active', 'internal_name', 'position', 'all_sales_channels', 'limit_sales_channels',
'available_from', 'available_until', 'subevent_mode', 'condition_all_products',
'condition_limit_products', 'condition_apply_to_addons', 'condition_min_count', 'condition_min_value',
'benefit_discount_matching_percent', 'benefit_only_apply_to_cheapest_n_matches',
'benefit_same_products', 'benefit_limit_products', 'benefit_apply_to_addons',
'benefit_ignore_voucher_discounted', 'condition_ignore_voucher_discounted')
@@ -39,6 +48,7 @@ class DiscountSerializer(I18nAwareModelSerializer):
super().__init__(*args, **kwargs)
self.fields['condition_limit_products'].queryset = self.context['event'].items.all()
self.fields['benefit_limit_products'].queryset = self.context['event'].items.all()
self.fields['limit_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
def validate(self, data):
data = super().validate(data)

View File

@@ -35,7 +35,7 @@
import logging
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import transaction
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
@@ -46,10 +46,15 @@ from rest_framework import serializers
from rest_framework.fields import ChoiceField, Field
from rest_framework.relations import SlugRelatedField
from pretix.api.serializers import CompatibleJSONField
from pretix.api.serializers import (
CompatibleJSONField, SalesChannelMigrationMixin,
)
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.settings import SettingsSerializer
from pretix.base.models import Device, Event, TaxRule, TeamAPIToken
from pretix.base.models import (
CartPosition, Device, Event, OrderPosition, SalesChannel, Seat, TaxRule,
TeamAPIToken, Voucher,
)
from pretix.base.models.event import SubEvent
from pretix.base.models.items import (
ItemMetaProperty, SubEventItem, SubEventItemVariation,
@@ -161,7 +166,7 @@ class ValidKeysField(Field):
}
class EventSerializer(I18nAwareModelSerializer):
class EventSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
meta_data = MetaDataField(required=False, source='*')
item_meta_properties = MetaPropertyField(required=False, source='*')
plugins = PluginsField(required=False, source='*')
@@ -170,6 +175,13 @@ class EventSerializer(I18nAwareModelSerializer):
valid_keys = ValidKeysField(source='*', read_only=True)
best_availability_state = serializers.IntegerField(allow_null=True, read_only=True)
public_url = serializers.SerializerMethodField('get_event_url', read_only=True)
limit_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
def get_event_url(self, event):
return build_absolute_uri(event, 'presale:event.index')
@@ -180,7 +192,7 @@ class EventSerializer(I18nAwareModelSerializer):
'date_to', 'date_admission', 'is_public', 'presale_start',
'presale_end', 'location', 'geo_lat', 'geo_lon', 'has_subevents', 'meta_data', 'seating_plan',
'plugins', 'seat_category_mapping', 'timezone', 'item_meta_properties', 'valid_keys',
'sales_channels', 'best_availability_state', 'public_url')
'all_sales_channels', 'limit_sales_channels', 'best_availability_state', 'public_url')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -188,6 +200,7 @@ class EventSerializer(I18nAwareModelSerializer):
self.fields.pop('valid_keys')
if not self.context.get('request') or 'with_availability_for' not in self.context['request'].GET:
self.fields.pop('best_availability_state')
self.fields['limit_sales_channels'].child_relation.queryset = self.context['organizer'].sales_channels.all()
def validate(self, data):
data = super().validate(data)
@@ -269,13 +282,17 @@ class EventSerializer(I18nAwareModelSerializer):
from pretix.base.plugins import get_all_plugins
plugins_available = {
p.module for p in get_all_plugins(self.instance)
p.module: p for p in get_all_plugins(self.instance)
if not p.name.startswith('.') and getattr(p, 'visible', True)
}
settings_holder = self.instance if self.instance and self.instance.pk else self.context['organizer']
for plugin in value.get('plugins'):
if plugin not in plugins_available:
raise ValidationError(_('Unknown plugin: \'{name}\'.').format(name=plugin))
if getattr(plugins_available[plugin], 'restricted', False):
if plugin not in settings_holder.settings.allowed_restricted_plugins:
raise ValidationError(_('Restricted plugin: \'{name}\'.').format(name=plugin))
return value
@@ -472,7 +489,8 @@ class SubEventSerializer(I18nAwareModelSerializer):
fields = ('id', 'name', 'date_from', 'date_to', 'active', 'date_admission',
'presale_start', 'presale_end', 'location', 'geo_lat', 'geo_lon', 'event', 'is_public',
'frontpage_text', 'seating_plan', 'item_price_overrides', 'variation_price_overrides',
'meta_data', 'seat_category_mapping', 'last_modified', 'best_availability_state')
'meta_data', 'seat_category_mapping', 'last_modified', 'best_availability_state',
'comment')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -683,10 +701,12 @@ class EventSettingsSerializer(SettingsSerializer):
'locales',
'locale',
'region',
'last_order_modification_date',
'allow_modifications',
'allow_modifications_after_checkin',
'last_order_modification_date',
'show_quota_left',
'waiting_list_enabled',
'waiting_list_auto_disable',
'waiting_list_hours',
'waiting_list_auto',
'waiting_list_names_asked',
@@ -733,6 +753,7 @@ class EventSettingsSerializer(SettingsSerializer):
'payment_term_accept_late',
'payment_explanation',
'payment_pending_hidden',
'payment_giftcard__enabled',
'mail_days_order_expire_warning',
'ticket_download',
'ticket_download_date',
@@ -824,6 +845,7 @@ class EventSettingsSerializer(SettingsSerializer):
'reusable_media_type_nfc_mf0aes_autocreate_giftcard',
'reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency',
'reusable_media_type_nfc_mf0aes_random_uid',
'seating_allow_blocked_seats_for_channel',
]
readonly_fields = [
# These are read-only since they are currently only settable on organizers, not events
@@ -949,3 +971,77 @@ class ItemMetaPropertiesSerializer(I18nAwareModelSerializer):
class Meta:
model = ItemMetaProperty
fields = ('id', 'name', 'default', 'required', 'allowed_values')
def prefetch_by_id(items, qs, id_attr, target_attr):
"""
Prefetches a related object on each item in the given list of items by searching by id or another
unique field. The id value is read from the attribute on item specified in `id_attr`, searched on queryset `qs` by
the primary key, and the resulting prefetched model object is stored into `target_attr` on the item.
"""
ids = [getattr(item, id_attr) for item in items if getattr(item, id_attr)]
if ids:
result = qs.in_bulk(id_list=ids)
for item in items:
setattr(item, target_attr, result.get(getattr(item, id_attr)))
class SeatSerializer(I18nAwareModelSerializer):
orderposition = serializers.IntegerField(source='orderposition_id')
cartposition = serializers.IntegerField(source='cartposition_id')
voucher = serializers.IntegerField(source='voucher_id')
class Meta:
model = Seat
read_only_fields = (
'id', 'subevent', 'zone_name', 'row_name', 'row_label',
'seat_number', 'seat_label', 'seat_guid', 'product',
'orderposition', 'cartposition', 'voucher',
)
fields = (
'id', 'subevent', 'zone_name', 'row_name', 'row_label',
'seat_number', 'seat_label', 'seat_guid', 'product', 'blocked',
'orderposition', 'cartposition', 'voucher',
)
def prefetch_expanded_data(self, items, request, expand_fields):
if 'orderposition' in expand_fields:
if 'can_view_orders' not in request.eventpermset:
raise PermissionDenied('can_view_orders permission required for expand=orderposition')
prefetch_by_id(items, OrderPosition.objects.prefetch_related('order'), 'orderposition_id', 'orderposition')
if 'cartposition' in expand_fields:
if 'can_view_orders' not in request.eventpermset:
raise PermissionDenied('can_view_orders permission required for expand=cartposition')
prefetch_by_id(items, CartPosition.objects, 'cartposition_id', 'cartposition')
if 'voucher' in expand_fields:
if 'can_view_vouchers' not in request.eventpermset:
raise PermissionDenied('can_view_vouchers permission required for expand=voucher')
prefetch_by_id(items, Voucher.objects, 'voucher_id', 'voucher')
def __init__(self, instance, *args, **kwargs):
if not kwargs.get('data'):
self.prefetch_expanded_data(instance if hasattr(instance, '__iter__') else [instance],
kwargs['context']['request'],
kwargs['context']['expand_fields'])
super().__init__(instance, *args, **kwargs)
if 'orderposition' in self.context['expand_fields']:
from pretix.api.serializers.media import (
NestedOrderPositionSerializer,
)
self.fields['orderposition'] = NestedOrderPositionSerializer(read_only=True, context=self.context['order_context'])
try:
del self.fields['orderposition'].fields['seat']
except KeyError:
pass
if 'cartposition' in self.context['expand_fields']:
from pretix.api.serializers.cart import CartPositionSerializer
self.fields['cartposition'] = CartPositionSerializer(read_only=True)
del self.fields['cartposition'].fields['seat']
if 'voucher' in self.context['expand_fields']:
from pretix.api.serializers.voucher import VoucherSerializer
self.fields['voucher'] = VoucherSerializer(read_only=True)
del self.fields['voucher'].fields['seat']

View File

@@ -42,31 +42,43 @@ from django.utils.functional import cached_property, lazy
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from pretix.api.serializers import SalesChannelMigrationMixin
from pretix.api.serializers.event import MetaDataField
from pretix.api.serializers.fields import UploadedFileField
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.base.models import (
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemVariation,
ItemVariationMetaValue, Question, QuestionOption, Quota,
ItemVariationMetaValue, Question, QuestionOption, Quota, SalesChannel,
)
class InlineItemVariationSerializer(I18nAwareModelSerializer):
class InlineItemVariationSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
price = serializers.DecimalField(read_only=True, decimal_places=2, max_digits=13,
coerce_to_string=True)
meta_data = MetaDataField(required=False, source='*')
limit_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price', 'free_price_suggestion', 'require_approval',
'require_membership', 'require_membership_types', 'require_membership_hidden',
'checkin_attention', 'checkin_text', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher', 'meta_data')
'checkin_attention', 'checkin_text',
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
'all_sales_channels', 'limit_sales_channels', 'hide_without_voucher', 'meta_data')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['require_membership_types'].queryset = lazy(lambda: self.context['event'].organizer.membership_types.all(), QuerySet)
self.fields['limit_sales_channels'].child_relation.queryset = (
self.context['event'].organizer.sales_channels.all() if 'event' in self.context else SalesChannel.objects.none()
)
def validate_meta_data(self, value):
for key in value['meta_data'].keys():
@@ -75,32 +87,45 @@ class InlineItemVariationSerializer(I18nAwareModelSerializer):
return value
class ItemVariationSerializer(I18nAwareModelSerializer):
class ItemVariationSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
price = serializers.DecimalField(read_only=True, decimal_places=2, max_digits=13,
coerce_to_string=True)
meta_data = MetaDataField(required=False, source='*')
limit_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price', 'free_price_suggestion', 'require_approval',
'require_membership', 'require_membership_types', 'require_membership_hidden',
'checkin_attention', 'checkin_text', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher', 'meta_data')
'checkin_attention', 'checkin_text',
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
'all_sales_channels', 'limit_sales_channels', 'hide_without_voucher', 'meta_data')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['require_membership_types'].queryset = self.context['event'].organizer.membership_types.all()
self.fields['limit_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
@transaction.atomic
def create(self, validated_data):
meta_data = validated_data.pop('meta_data', None)
require_membership_types = validated_data.pop('require_membership_types', [])
limit_sales_channels = validated_data.pop('limit_sales_channels', [])
variation = ItemVariation.objects.create(**validated_data)
if require_membership_types:
variation.require_membership_types.add(*require_membership_types)
if limit_sales_channels:
variation.limit_sales_channels.add(*limit_sales_channels)
# Meta data
if meta_data is not None:
for key, value in meta_data.items():
@@ -221,7 +246,7 @@ class ItemTaxRateField(serializers.Field):
return str(Decimal('0.00'))
class ItemSerializer(I18nAwareModelSerializer):
class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
addons = InlineItemAddOnSerializer(many=True, required=False)
bundles = InlineItemBundleSerializer(many=True, required=False)
variations = InlineItemVariationSerializer(many=True, required=False)
@@ -230,12 +255,20 @@ class ItemSerializer(I18nAwareModelSerializer):
picture = UploadedFileField(required=False, allow_null=True, allowed_types=(
'image/png', 'image/jpeg', 'image/gif'
), max_size=settings.FILE_UPLOAD_MAX_SIZE_IMAGE)
limit_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = Item
fields = ('id', 'category', 'name', 'internal_name', 'active', 'sales_channels', 'description',
'default_price', 'free_price', 'free_price_suggestion', 'tax_rate', 'tax_rule', 'admission',
'personalized', 'position', 'picture', 'available_from', 'available_until',
fields = ('id', 'category', 'name', 'internal_name', 'active', 'all_sales_channels', 'limit_sales_channels',
'description', 'default_price', 'free_price', 'free_price_suggestion', 'tax_rate', 'tax_rule', 'admission',
'personalized', 'position', 'picture',
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
'min_per_order', 'max_per_order', 'checkin_attention', 'checkin_text', 'has_variations', 'variations',
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
@@ -256,6 +289,8 @@ class ItemSerializer(I18nAwareModelSerializer):
if not self.read_only:
self.fields['require_membership_types'].queryset = self.context['event'].organizer.membership_types.all()
self.fields['grant_membership_type'].queryset = self.context['event'].organizer.membership_types.all()
self.fields['limit_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
self.fields['variations'].child.fields['limit_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
def validate(self, data):
data = super().validate(data)
@@ -332,7 +367,10 @@ class ItemSerializer(I18nAwareModelSerializer):
meta_data = validated_data.pop('meta_data', None)
picture = validated_data.pop('picture', None)
require_membership_types = validated_data.pop('require_membership_types', [])
limit_sales_channels = validated_data.pop('limit_sales_channels', [])
item = Item.objects.create(**validated_data)
if limit_sales_channels:
item.limit_sales_channels.add(*limit_sales_channels)
if picture:
item.picture.save(os.path.basename(picture.name), picture)
if require_membership_types:
@@ -340,10 +378,13 @@ class ItemSerializer(I18nAwareModelSerializer):
for variation_data in variations_data:
require_membership_types = variation_data.pop('require_membership_types', [])
limit_sales_channels = variation_data.pop('limit_sales_channels', [])
var_meta_data = variation_data.pop('meta_data', {})
v = ItemVariation.objects.create(item=item, **variation_data)
if require_membership_types:
v.require_membership_types.add(*require_membership_types)
if limit_sales_channels:
v.limit_sales_channels.add(*limit_sales_channels)
if var_meta_data is not None:
for key, value in var_meta_data.items():

View File

@@ -46,13 +46,12 @@ from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.item import (
InlineItemVariationSerializer, ItemSerializer, QuestionSerializer,
)
from pretix.base.channels import get_all_sales_channels
from pretix.base.decimal import round_decimal
from pretix.base.i18n import language
from pretix.base.models import (
CachedFile, Checkin, Customer, Invoice, InvoiceAddress, InvoiceLine, Item,
ItemVariation, Order, OrderPosition, Question, QuestionAnswer,
ReusableMedium, Seat, SubEvent, TaxRule, Voucher,
ReusableMedium, SalesChannel, Seat, SubEvent, TaxRule, Voucher,
)
from pretix.base.models.orders import (
BlockedTicketSecret, CartPosition, OrderFee, OrderPayment, OrderRefund,
@@ -166,7 +165,7 @@ class InlineSeatSerializer(I18nAwareModelSerializer):
class Meta:
model = Seat
fields = ('id', 'name', 'seat_guid')
fields = ('id', 'name', 'seat_guid', 'zone_name', 'row_name', 'row_label', 'seat_label', 'seat_number')
class AnswerSerializer(I18nAwareModelSerializer):
@@ -486,11 +485,11 @@ class OrderPositionSerializer(I18nAwareModelSerializer):
'company', 'street', 'zipcode', 'city', 'country', 'state', 'discount',
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat', 'canceled',
'valid_from', 'valid_until', 'blocked')
'valid_from', 'valid_until', 'blocked', 'voucher_budget_use')
read_only_fields = (
'id', 'order', 'positionid', 'item', 'variation', 'price', 'voucher', 'tax_rate', 'tax_value', 'secret',
'addon_to', 'subevent', 'checkins', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data',
'seat', 'canceled', 'discount', 'valid_from', 'valid_until', 'blocked'
'seat', 'canceled', 'discount', 'valid_from', 'valid_until', 'blocked', 'voucher_budget_use'
)
def __init__(self, *args, **kwargs):
@@ -564,6 +563,8 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
attendee_name = AttendeeNameField(source='*')
attendee_name_parts = AttendeeNamePartsField(source='*')
order__status = serializers.SlugRelatedField(read_only=True, slug_field='status', source='order')
order__valid_if_pending = serializers.SlugRelatedField(read_only=True, slug_field='valid_if_pending', source='order')
order__require_approval = serializers.SlugRelatedField(read_only=True, slug_field='require_approval', source='order')
class Meta:
model = OrderPosition
@@ -571,7 +572,8 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
'company', 'street', 'zipcode', 'city', 'country', 'state',
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat', 'require_attention',
'order__status', 'valid_from', 'valid_until', 'blocked')
'order__status', 'order__valid_if_pending', 'order__require_approval', 'valid_from', 'valid_until',
'blocked')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -583,7 +585,7 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
self.fields['item'] = ItemSerializer(read_only=True, context=self.context)
if 'variation' in self.context['expand']:
self.fields['variation'] = InlineItemVariationSerializer(read_only=True)
self.fields['variation'] = InlineItemVariationSerializer(read_only=True, context=self.context)
if 'answers.question' in self.context['expand']:
self.fields['answers'].child.fields['question'] = QuestionSerializer(read_only=True)
@@ -711,6 +713,11 @@ class OrderSerializer(I18nAwareModelSerializer):
payment_provider = OrderPaymentTypeField(source='*', read_only=True)
url = OrderURLField(source='*', read_only=True)
customer = serializers.SlugRelatedField(slug_field='identifier', read_only=True)
sales_channel = serializers.SlugRelatedField(
slug_field='identifier',
queryset=SalesChannel.objects.none(),
required=False,
)
class Meta:
model = Order
@@ -719,7 +726,7 @@ class OrderSerializer(I18nAwareModelSerializer):
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
'url', 'customer', 'valid_if_pending'
'url', 'customer', 'valid_if_pending', 'api_meta'
)
read_only_fields = (
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
@@ -729,6 +736,10 @@ class OrderSerializer(I18nAwareModelSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if "organizer" in self.context:
self.fields["sales_channel"].queryset = self.context["organizer"].sales_channels.all()
else:
self.fields["sales_channel"].queryset = self.context["event"].organizer.sales_channels.all()
if not self.context['pdf_data']:
self.fields['positions'].child.fields.pop('pdf_data', None)
@@ -775,7 +786,7 @@ class OrderSerializer(I18nAwareModelSerializer):
# Even though all fields that shouldn't be edited are marked as read_only in the serializer
# (hopefully), we'll be extra careful here and be explicit about the model fields we update.
update_fields = ['comment', 'custom_followup_at', 'checkin_attention', 'checkin_text', 'email', 'locale',
'phone', 'valid_if_pending']
'phone', 'valid_if_pending', 'api_meta']
if 'invoice_address' in validated_data:
iadata = validated_data.pop('invoice_address')
@@ -1030,19 +1041,25 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
require_approval = serializers.BooleanField(default=False, required=False)
simulate = serializers.BooleanField(default=False, required=False)
customer = serializers.SlugRelatedField(slug_field='identifier', queryset=Customer.objects.none(), required=False)
sales_channel = serializers.SlugRelatedField(
slug_field='identifier',
queryset=SalesChannel.objects.none(),
required=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['positions'].child.fields['voucher'].queryset = self.context['event'].vouchers.all()
self.fields['customer'].queryset = self.context['event'].organizer.customers.all()
self.fields['expires'].required = False
self.fields["sales_channel"].queryset = self.context["event"].organizer.sales_channels.all()
class Meta:
model = Order
fields = ('code', 'status', 'testmode', 'email', 'phone', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
'invoice_address', 'positions', 'checkin_attention', 'checkin_text', 'payment_info', 'payment_date',
'consume_carts', 'force', 'send_email', 'simulate', 'customer', 'custom_followup_at',
'require_approval', 'valid_if_pending', 'expires')
'require_approval', 'valid_if_pending', 'expires', 'api_meta')
def validate_payment_provider(self, pp):
if pp is None:
@@ -1056,11 +1073,6 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
raise ValidationError('Expiration date must be in the future.')
return expires
def validate_sales_channel(self, channel):
if channel not in get_all_sales_channels():
raise ValidationError('Unknown sales channel.')
return channel
def validate_code(self, code):
if code and Order.objects.filter(event__organizer=self.context['event'].organizer, code=code).exists():
raise ValidationError(
@@ -1122,20 +1134,6 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
raise ValidationError(errs)
return data
def validate_testmode(self, testmode):
if 'sales_channel' in self.initial_data:
try:
sales_channel = get_all_sales_channels()[self.initial_data['sales_channel']]
if testmode and not sales_channel.testmode_supported:
raise ValidationError('This sales channel does not provide support for test mode.')
except KeyError:
# We do not need to raise a ValidationError here, since there is another check to validate the
# sales_channel
pass
return testmode
def create(self, validated_data):
fees_data = validated_data.pop('fees') if 'fees' in validated_data else []
positions_data = validated_data.pop('positions') if 'positions' in validated_data else []
@@ -1144,9 +1142,16 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
payment_date = validated_data.pop('payment_date', now())
force = validated_data.pop('force', False)
simulate = validated_data.pop('simulate', False)
if not validated_data.get("sales_channel"):
validated_data["sales_channel"] = self.context['event'].organizer.sales_channels.get(identifier="web")
if validated_data.get("testmode") and not validated_data["sales_channel"].type_instance.testmode_supported:
raise ValidationError({"testmode": ["This sales channel does not provide support for test mode."]})
self._send_mail = validated_data.pop('send_email', False)
if self._send_mail is None:
self._send_mail = validated_data.get('sales_channel') in self.context['event'].settings.mail_sales_channel_placed_paid
self._send_mail = validated_data["sales_channel"].identifier in self.context['event'].settings.mail_sales_channel_placed_paid
if 'invoice_address' in validated_data:
iadata = validated_data.pop('invoice_address')
@@ -1306,7 +1311,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
errs[i]['seat'] = ['The specified seat does not exist.']
else:
seat_usage[seat] += 1
if (seat_usage[seat] > 0 and not seat.is_available(sales_channel=validated_data.get('sales_channel', 'web'))) or seat_usage[seat] > 1:
sales_channel_id = validated_data['sales_channel'].identifier
if (seat_usage[seat] > 0 and not seat.is_available(sales_channel=sales_channel_id)) or seat_usage[seat] > 1:
errs[i]['seat'] = [gettext_lazy('The selected seat "{seat}" is not available.').format(seat=seat.name)]
elif seated:
errs[i]['seat'] = ['The specified product requires to choose a seat.']
@@ -1315,7 +1321,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
if 'valid_from' not in pos_data and 'valid_until' not in pos_data:
valid_from, valid_until = pos_data['item'].compute_validity(
requested_start=(
max(requested_valid_from, now())
requested_valid_from
if requested_valid_from and pos_data['item'].validity_dynamic_start_choice
else now()
),
@@ -1365,6 +1371,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
if validated_data.get('locale', None) is None:
validated_data['locale'] = self.context['event'].settings.locale
order = Order(event=self.context['event'], **validated_data)
if not validated_data.get('expires'):
order.set_expires(subevents=[p.get('subevent') for p in positions_data])
@@ -1439,6 +1446,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
if not pos.item.tax_rule or pos.item.tax_rule.price_includes_tax:
price_after_voucher = max(pos.price, pos.voucher.calculate_price(listed_price))
else:
pos._calculate_tax(invoice_address=ia)
price_after_voucher = max(pos.price - pos.tax_value, pos.voucher.calculate_price(listed_price))
else:
price_after_voucher = listed_price
@@ -1466,7 +1474,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
answers_data = pos_data.pop('answers', [])
use_reusable_medium = pos_data.pop('use_reusable_medium', None)
pos = pos_data['__instance']
pos._calculate_tax()
pos._calculate_tax(invoice_address=ia)
if simulate:
pos = WrappedModel(pos)
@@ -1585,7 +1593,10 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
if order.total == Decimal('0.00') and validated_data.get('status') == Order.STATUS_PAID and not payment_provider:
payment_provider = 'free'
if order.total == Decimal('0.00') and validated_data.get('status') != Order.STATUS_PAID:
if order.total != Decimal('0.00') and order.event.currency == "XXX":
raise ValidationError('Paid products not supported without a valid currency.')
if order.total == Decimal('0.00') and validated_data.get('status') != Order.STATUS_PAID and not validated_data.get('require_approval'):
order.status = Order.STATUS_PAID
order.save()
order.payments.create(
@@ -1597,6 +1608,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
elif validated_data.get('status') == Order.STATUS_PAID:
if not payment_provider:
raise ValidationError('You cannot create a paid order without a payment provider.')
if validated_data.get('require_approval'):
raise ValidationError('You cannot create a paid order that requires approval.')
order.payments.create(
amount=order.total,
provider=payment_provider,

View File

@@ -38,7 +38,7 @@ from pretix.base.i18n import get_language_without_region
from pretix.base.models import (
Customer, Device, GiftCard, GiftCardAcceptance, GiftCardTransaction,
Membership, MembershipType, OrderPosition, Organizer, ReusableMedium,
SeatingPlan, Team, TeamAPIToken, TeamInvite, User,
SalesChannel, SeatingPlan, Team, TeamAPIToken, TeamInvite, User,
)
from pretix.base.models.seating import SeatingPlanLayoutValidator
from pretix.base.services.mail import SendMailException, mail
@@ -79,8 +79,8 @@ class CustomerSerializer(I18nAwareModelSerializer):
class Meta:
model = Customer
fields = ('identifier', 'external_identifier', 'email', 'name', 'name_parts', 'is_active', 'is_verified', 'last_login', 'date_joined',
'locale', 'last_modified', 'notes')
fields = ('identifier', 'external_identifier', 'email', 'phone', 'name', 'name_parts', 'is_active',
'is_verified', 'last_login', 'date_joined', 'locale', 'last_modified', 'notes')
def update(self, instance, validated_data):
if instance and instance.provider_id:
@@ -165,6 +165,36 @@ class FlexibleTicketRelatedField(serializers.PrimaryKeyRelatedField):
self.fail('incorrect_type', data_type=type(data).__name__)
class SalesChannelSerializer(I18nAwareModelSerializer):
type = serializers.CharField(default="api")
class Meta:
model = SalesChannel
fields = ('identifier', 'type', 'label', 'position')
def validate_type(self, value):
if (not self.instance or not self.instance.pk) and value != "api":
raise ValidationError(
"You can currently only create channels of type 'api' through the API."
)
if value and self.instance and self.instance.pk and self.instance.type != value:
raise ValidationError(
"You cannot change the type of a sales channel."
)
return value
def validate_identifier(self, value):
if (not self.instance or not self.instance.pk) and not value.startswith("api."):
raise ValidationError(
"Your identifier needs to start with 'api.'."
)
if value and self.instance and self.instance.pk and self.instance.identifier != value:
raise ValidationError(
"You cannot change the identifier of a sales channel."
)
return value
class GiftCardSerializer(I18nAwareModelSerializer):
value = serializers.DecimalField(max_digits=13, decimal_places=2, min_value=Decimal('0.00'))
owner_ticket = FlexibleTicketRelatedField(required=False, allow_null=True, queryset=OrderPosition.all.none())
@@ -239,7 +269,7 @@ class TeamSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = (
'id', 'name', 'all_events', 'limit_events', 'can_create_events', 'can_change_teams',
'id', 'name', 'require_2fa', 'all_events', 'limit_events', 'can_create_events', 'can_change_teams',
'can_change_organizer_settings', 'can_manage_gift_cards', 'can_change_event_settings',
'can_change_items', 'can_view_orders', 'can_change_orders', 'can_view_vouchers',
'can_change_vouchers', 'can_checkin_orders', 'can_manage_customers', 'can_manage_reusable_media'

View File

@@ -89,6 +89,7 @@ class SettingsSerializer(serializers.Serializer):
except OSError: # pragma: no cover
logger.error('Deleting file %s failed.' % fname.name)
instance.delete(attr)
self.changed_data.append(attr)
else:
# file is unchanged
continue

View File

@@ -56,6 +56,7 @@ orga_router.register(r'webhooks', webhooks.WebHookViewSet)
orga_router.register(r'seatingplans', organizer.SeatingPlanViewSet)
orga_router.register(r'giftcards', organizer.GiftCardViewSet)
orga_router.register(r'customers', organizer.CustomerViewSet)
orga_router.register(r'saleschannels', organizer.SalesChannelViewSet)
orga_router.register(r'memberships', organizer.MembershipViewSet)
orga_router.register(r'membershiptypes', organizer.MembershipTypeViewSet)
orga_router.register(r'reusablemedia', media.ReusableMediaViewSet)
@@ -86,6 +87,7 @@ event_router.register(r'invoices', order.InvoiceViewSet)
event_router.register(r'revokedsecrets', order.RevokedSecretViewSet, basename='revokedsecrets')
event_router.register(r'blockedsecrets', order.BlockedSecretViewSet, basename='blockedsecrets')
event_router.register(r'taxrules', event.TaxRuleViewSet)
event_router.register(r'seats', event.SeatViewSet)
event_router.register(r'waitinglistentries', waitinglist.WaitingListViewSet)
event_router.register(r'checkinlists', checkin.CheckinListViewSet)
event_router.register(r'cartpositions', cart.CartPositionViewSet)
@@ -94,6 +96,9 @@ event_router.register(r'exporters', exporters.EventExportersViewSet, basename='e
event_router.register(r'shredders', shredders.EventShreddersViewSet, basename='shredders')
event_router.register(r'item_meta_properties', event.ItemMetaPropertiesViewSet)
subevent_router = routers.DefaultRouter()
subevent_router.register(r'seats', event.SeatViewSet)
checkinlist_router = routers.DefaultRouter()
checkinlist_router.register(r'positions', checkin.CheckinListPositionViewSet, basename='checkinlistpos')
@@ -131,6 +136,7 @@ urlpatterns = [
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/settings/$', event.EventSettingsView.as_view(),
name="event.settings"),
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/', include(event_router.urls)),
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/subevents/(?P<subevent>\d+)/', include(subevent_router.urls)),
re_path(r'^organizers/(?P<organizer>[^/]+)/teams/(?P<team>[^/]+)/', include(team_router.urls)),
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/items/(?P<item>[^/]+)/', include(item_router.urls)),
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/questions/(?P<question>[^/]+)/',

View File

@@ -211,8 +211,12 @@ class CartPositionViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnly
if validated_data.get('seat'):
# Assumption: Add-ons currently can't have seats, thus we only need to check the main product
if validated_data.get('sales_channel'):
sales_channel_id = validated_data.get('sales_channel').identifier
else:
sales_channel_id = "web"
if not validated_data['seat'].is_available(
sales_channel=validated_data.get('sales_channel', 'web'),
sales_channel=sales_channel_id,
distance_ignore_cart_id=validated_data['cart_id'],
ignore_voucher_id=validated_data['voucher'].pk if validated_data.get('voucher') else None,
):

View File

@@ -35,6 +35,7 @@ from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import gettext
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from packaging.version import parse
@@ -114,7 +115,7 @@ class CheckinListViewSet(viewsets.ModelViewSet):
if 'subevent' in self.request.query_params.getlist('expand'):
qs = qs.prefetch_related(
'subevent', 'subevent__event', 'subevent__subeventitem_set', 'subevent__subeventitemvariation_set',
'subevent__seat_category_mappings', 'subevent__meta_values'
'subevent__seat_category_mappings', 'subevent__meta_values', 'auto_checkin_sales_channels'
)
return qs
@@ -285,6 +286,8 @@ with scopes_disabled():
return queryset.filter(last_checked_in__isnull=not value)
def check_rules_qs(self, queryset, name, value):
if not value:
return queryset
if not self.checkinlist.rules:
return queryset
return queryset.filter(
@@ -403,7 +406,7 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
'item__variations').select_related('item__tax_rule')
if expand and 'variation' in expand:
qs = qs.prefetch_related('variation')
qs = qs.prefetch_related('variation', 'variation__meta_values')
return qs
@@ -584,6 +587,32 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
'list': MiniCheckinListSerializer(list_by_event[revoked_matches[0].event_id]).data,
}, status=400)
else:
if media.linked_orderposition.order.event_id not in list_by_event:
# Medium exists but connected ticket is for the wrong event
if not simulate:
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
'datetime': datetime,
'type': checkin_type,
'list': checkinlists[0].pk,
'barcode': raw_barcode,
'searched_lists': [cl.pk for cl in checkinlists]
}, user=user, auth=auth)
Checkin.objects.create(
position=None,
successful=False,
error_reason=Checkin.REASON_INVALID,
error_explanation=gettext('Medium connected to other event'),
**common_checkin_args,
)
return Response({
'detail': 'Not found.', # for backwards compatibility
'status': 'error',
'reason': Checkin.REASON_INVALID,
'reason_explanation': gettext('Medium connected to other event'),
'require_attention': False,
'checkin_texts': [],
'list': MiniCheckinListSerializer(checkinlists[0]).data,
}, status=404)
op_candidates = [media.linked_orderposition]
if list_by_event[media.linked_orderposition.order.event_id].addon_match:
op_candidates += list(media.linked_orderposition.addons.all())

View File

@@ -60,7 +60,9 @@ class DiscountViewSet(ConditionalListView, viewsets.ModelViewSet):
write_permission = 'can_change_items'
def get_queryset(self):
return self.request.event.discounts.all()
return self.request.event.discounts.prefetch_related(
'limit_sales_channels',
)
def perform_create(self, serializer):
serializer.save(event=self.request.event)

View File

@@ -40,27 +40,28 @@ from django.utils.timezone import now
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import serializers, views, viewsets
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.exceptions import (
NotFound, PermissionDenied, ValidationError,
)
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from pretix.api.auth.permission import EventCRUDPermission
from pretix.api.pagination import TotalOrderingFilter
from pretix.api.serializers.event import (
CloneEventSerializer, DeviceEventSettingsSerializer, EventSerializer,
EventSettingsSerializer, ItemMetaPropertiesSerializer, SubEventSerializer,
TaxRuleSerializer,
EventSettingsSerializer, ItemMetaPropertiesSerializer, SeatSerializer,
SubEventSerializer, TaxRuleSerializer,
)
from pretix.api.views import ConditionalListView
from pretix.base.models import (
CartPosition, Device, Event, ItemMetaProperty, SeatCategoryMapping,
CartPosition, Device, Event, ItemMetaProperty, Seat, SeatCategoryMapping,
TaxRule, TeamAPIToken,
)
from pretix.base.models.event import SubEvent
from pretix.base.services.quotas import QuotaAvailability
from pretix.base.settings import SETTINGS_AFFECTING_CSS
from pretix.helpers.dicts import merge_dicts
from pretix.helpers.i18n import i18ncomp
from pretix.presale.style import regenerate_css
from pretix.presale.views.organizer import filter_qs_by_attr
with scopes_disabled():
@@ -115,7 +116,10 @@ with scopes_disabled():
return queryset.exclude(expr)
def sales_channel_qs(self, queryset, name, value):
return queryset.filter(sales_channels__contains=value)
return queryset.filter(
Q(all_sales_channels=True) |
Q(limit_sales_channels__identifier=value)
)
def search_qs(self, queryset, name, value):
return queryset.filter(
@@ -137,6 +141,12 @@ class EventViewSet(viewsets.ModelViewSet):
ordering_fields = ('date_from', 'slug')
filterset_class = EventFilter
def get_serializer_context(self):
return {
**super().get_serializer_context(),
"organizer": self.request.organizer,
}
def get_copy_from_queryset(self):
if isinstance(self.request.auth, (TeamAPIToken, Device)):
return self.request.auth.get_events_with_any_permission()
@@ -155,13 +165,20 @@ class EventViewSet(viewsets.ModelViewSet):
qs = filter_qs_by_attr(qs, self.request)
if 'with_availability_for' in self.request.GET:
qs = Event.annotated(qs, channel=self.request.GET.get('with_availability_for'))
qs = Event.annotated(
qs,
channel=get_object_or_404(
self.request.organizer.sales_channels,
identifier=self.request.GET.get('with_availability_for')
)
)
return qs.prefetch_related(
'organizer',
'meta_values',
'meta_values__property',
'item_meta_properties',
'limit_sales_channels',
Prefetch(
'seat_category_mappings',
to_attr='_seat_category_mappings',
@@ -190,7 +207,10 @@ class EventViewSet(viewsets.ModelViewSet):
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
@transaction.atomic()
def perform_update(self, serializer):
original_data = self.get_serializer(instance=serializer.instance).data
current_live_value = serializer.instance.live
updated_live_value = serializer.validated_data.get('live', None)
current_plugins_value = serializer.instance.get_plugins()
@@ -198,6 +218,11 @@ class EventViewSet(viewsets.ModelViewSet):
super().perform_update(serializer)
if serializer.data == original_data:
# Performance optimization: If nothing was changed, we do not need to save or log anything.
# This costs us a few cycles on save, but avoids thousands of lines in our log.
return
if updated_live_value is not None and updated_live_value != current_live_value:
log_action = 'pretix.event.live.activated' if updated_live_value else 'pretix.event.live.deactivated'
serializer.instance.log_action(
@@ -262,8 +287,6 @@ class EventViewSet(viewsets.ModelViewSet):
new_event.is_public = serializer.validated_data['is_public']
if 'testmode' in serializer.validated_data:
new_event.testmode = serializer.validated_data['testmode']
if 'sales_channels' in serializer.validated_data:
new_event.sales_channels = serializer.validated_data['sales_channels']
if 'has_subevents' in serializer.validated_data:
new_event.has_subevents = serializer.validated_data['has_subevents']
if 'date_admission' in serializer.validated_data:
@@ -271,6 +294,10 @@ class EventViewSet(viewsets.ModelViewSet):
new_event.save()
if 'timezone' in serializer.validated_data:
new_event.settings.timezone = serializer.validated_data['timezone']
if 'all_sales_channels' in serializer.validated_data and 'sales_channels' in serializer.validated_data:
new_event.all_sales_channels = serializer.validated_data['all_sales_channels']
new_event.limit_sales_channels.set(serializer.validated_data['limit_sales_channels'])
else:
serializer.instance.set_defaults()
@@ -291,7 +318,7 @@ class EventViewSet(viewsets.ModelViewSet):
try:
with transaction.atomic():
instance.organizer.log_action(
'pretix.event.deleted', user=self.request.user,
'pretix.event.deleted', user=self.request.user, auth=self.request.auth,
data={
'event_id': instance.pk,
'name': str(instance.name),
@@ -373,7 +400,10 @@ with scopes_disabled():
return queryset.exclude(expr)
def sales_channel_qs(self, queryset, name, value):
return queryset.filter(event__sales_channels__contains=value)
return queryset.filter(
Q(event__all_sales_channels=True) |
Q(event__limit_sales_channels__identifier=value)
)
def search_qs(self, queryset, name, value):
return queryset.filter(
@@ -415,13 +445,19 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
elif self.request.user.is_authenticated:
qs = SubEvent.objects.filter(
event__organizer=self.request.organizer,
event__in=self.request.user.get_events_with_any_permission()
event__in=self.request.user.get_events_with_any_permission(request=self.request)
)
qs = filter_qs_by_attr(qs, self.request)
if 'with_availability_for' in self.request.GET:
qs = SubEvent.annotated(qs, channel=self.request.GET.get('with_availability_for'))
qs = SubEvent.annotated(
qs,
channel=get_object_or_404(
self.request.organizer.sales_channels,
identifier=self.request.GET.get('with_availability_for')
)
)
return qs.prefetch_related(
'event',
@@ -622,15 +658,88 @@ class EventSettingsView(views.APIView):
s.is_valid(raise_exception=True)
with transaction.atomic():
s.save()
self.request.event.log_action(
'pretix.event.settings', user=self.request.user, auth=self.request.auth, data={
k: v for k, v in s.validated_data.items()
}
)
if any(p in s.changed_data for p in SETTINGS_AFFECTING_CSS):
regenerate_css.apply_async(args=(request.event.pk,))
if s.changed_data:
self.request.event.log_action(
'pretix.event.settings', user=self.request.user, auth=self.request.auth, data={
k: v for k, v in s.validated_data.items()
}
)
s = EventSettingsSerializer(
instance=request.event.settings, event=request.event, context={
'request': request
})
return Response(s.data)
class SeatFilter(FilterSet):
is_available = django_filters.BooleanFilter(method="is_available_qs")
def is_available_qs(self, queryset, name, value):
expr = (
Q(orderposition_id__isnull=True, cartposition_id__isnull=True, voucher_id__isnull=True)
)
if self.request.event.settings.seating_minimal_distance:
expr = expr & Q(has_closeby_taken=False)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
class Meta:
model = Seat
fields = ('zone_name', 'row_name', 'row_label', 'seat_number', 'seat_label', 'seat_guid', 'blocked',)
class SeatViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = SeatSerializer
queryset = Seat.objects.none()
write_permission = 'can_change_event_settings'
filter_backends = (DjangoFilterBackend, )
filterset_class = SeatFilter
def get_queryset(self):
if self.request.event.has_subevents and 'subevent' in self.request.resolver_match.kwargs:
try:
subevent = self.request.event.subevents.get(pk=self.request.resolver_match.kwargs['subevent'])
except SubEvent.DoesNotExist:
raise NotFound('Subevent not found')
qs = Seat.annotated(
event_id=self.request.event.id,
subevent=subevent,
qs=subevent.seats.all(),
annotate_ids=True,
minimal_distance=self.request.event.settings.seating_minimal_distance,
distance_only_within_row=self.request.event.settings.seating_distance_only_within_row,
)
elif not self.request.event.has_subevents and 'subevent' not in self.request.resolver_match.kwargs:
qs = Seat.annotated(
event_id=self.request.event.id,
subevent=None,
qs=self.request.event.seats.all(),
annotate_ids=True,
minimal_distance=self.request.event.settings.seating_minimal_distance,
distance_only_within_row=self.request.event.settings.seating_distance_only_within_row,
)
else:
raise NotFound('Please use the subevent-specific endpoint' if self.request.event.has_subevents
else 'This event has no subevents')
return qs
def get_serializer_context(self):
ctx = super().get_serializer_context()
ctx['expand_fields'] = self.request.query_params.getlist('expand')
ctx['order_context'] = {
'event': self.request.event,
'pdf_data': None,
}
return ctx
def perform_update(self, serializer):
super().perform_update(serializer)
serializer.instance.event.log_action(
"pretix.event.seats.blocks.changed",
user=self.request.user,
auth=self.request.auth,
data={"seats": [serializer.instance.pk]},
)

View File

@@ -42,7 +42,7 @@ class IdempotencyQueryView(APIView):
idempotency_key = request.GET.get("key")
auth_hash_parts = '{}:{}'.format(
request.headers.get('Authorization', ''),
request.COOKIES.get(settings.SESSION_COOKIE_NAME, '')
request.COOKIES.get('__Host-' + settings.SESSION_COOKIE_NAME, request.COOKIES.get(settings.SESSION_COOKIE_NAME, ''))
)
auth_hash = sha1(auth_hash_parts.encode()).hexdigest()
if not idempotency_key:

View File

@@ -56,10 +56,17 @@ from pretix.base.models import (
)
from pretix.base.services.quotas import QuotaAvailability
from pretix.helpers.dicts import merge_dicts
from pretix.helpers.i18n import i18ncomp
with scopes_disabled():
class ItemFilter(FilterSet):
tax_rate = django_filters.CharFilter(method='tax_rate_qs')
search = django_filters.CharFilter(method='search_qs')
def search_qs(self, queryset, name, value):
return queryset.filter(
Q(internal_name__icontains=value) | Q(name__icontains=i18ncomp(value))
)
def tax_rate_qs(self, queryset, name, value):
if value in ("0", "None", "0.00"):
@@ -71,6 +78,18 @@ with scopes_disabled():
model = Item
fields = ['active', 'category', 'admission', 'tax_rate', 'free_price']
class ItemVariationFilter(FilterSet):
search = django_filters.CharFilter(method='search_qs')
def search_qs(self, queryset, name, value):
return queryset.filter(
Q(value__icontains=i18ncomp(value))
)
class Meta:
model = ItemVariation
fields = ['active']
class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = ItemSerializer
@@ -87,6 +106,7 @@ class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
'variations', 'addons', 'bundles', 'meta_values', 'meta_values__property',
'variations__meta_values', 'variations__meta_values__property',
'require_membership_types', 'variations__require_membership_types',
'limit_sales_channels', 'variations__limit_sales_channels',
).all()
def perform_create(self, serializer):
@@ -139,6 +159,7 @@ class ItemVariationViewSet(viewsets.ModelViewSet):
serializer_class = ItemVariationSerializer
queryset = ItemVariation.objects.none()
filter_backends = (DjangoFilterBackend, TotalOrderingFilter,)
filterset_class = ItemVariationFilter
ordering_fields = ('id', 'position')
ordering = ('id',)
permission = None
@@ -152,7 +173,8 @@ class ItemVariationViewSet(viewsets.ModelViewSet):
return self.item.variations.all().prefetch_related(
'meta_values',
'meta_values__property',
'require_membership_types'
'require_membership_types',
'limit_sales_channels',
)
def get_serializer_context(self):

View File

@@ -20,6 +20,7 @@
# <https://www.gnu.org/licenses/>.
#
import datetime
import logging
import mimetypes
import os
from decimal import Decimal
@@ -27,7 +28,7 @@ from zoneinfo import ZoneInfo
import django_filters
from django.conf import settings
from django.db import transaction
from django.db import IntegrityError, transaction
from django.db.models import (
Exists, F, OuterRef, Prefetch, Q, Subquery, prefetch_related_objects,
)
@@ -48,6 +49,7 @@ from rest_framework.mixins import CreateModelMixin
from rest_framework.permissions import SAFE_METHODS
from rest_framework.response import Response
from pretix.api.filters import MultipleCharFilter
from pretix.api.models import OAuthAccessToken
from pretix.api.pagination import TotalOrderingFilter
from pretix.api.serializers.order import (
@@ -96,6 +98,9 @@ from pretix.base.signals import (
)
from pretix.base.templatetags.money import money_filter
from pretix.control.signals import order_search_filter_q
from pretix.helpers import OF_SELF
logger = logging.getLogger(__name__)
with scopes_disabled():
class OrderFilter(FilterSet):
@@ -104,6 +109,7 @@ with scopes_disabled():
status = django_filters.CharFilter(field_name='status', lookup_expr='iexact')
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
created_since = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='gte')
created_before = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='lt')
subevent_after = django_filters.IsoDateTimeFilter(method='subevent_after_qs')
subevent_before = django_filters.IsoDateTimeFilter(method='subevent_before_qs')
search = django_filters.CharFilter(method='search_qs')
@@ -111,6 +117,8 @@ with scopes_disabled():
variation = django_filters.CharFilter(field_name='all_positions', lookup_expr='variation_id', distinct=True)
subevent = django_filters.CharFilter(field_name='all_positions', lookup_expr='subevent_id', distinct=True)
customer = django_filters.CharFilter(field_name='customer__identifier')
sales_channel = django_filters.CharFilter(field_name='sales_channel__identifier')
payment_provider = django_filters.CharFilter(method='provider_qs')
class Meta:
model = Order
@@ -134,6 +142,11 @@ with scopes_disabled():
)
return qs
def provider_qs(self, qs, name, value):
return qs.filter(Exists(
OrderPayment.objects.filter(order=OuterRef('pk'), provider=value)
))
def subevent_before_qs(self, qs, name, value):
if getattr(self.request, 'event', None):
subevents = self.request.event.subevents
@@ -225,7 +238,7 @@ class OrderViewSetMixin:
if 'customer' not in self.request.GET.getlist('exclude'):
qs = qs.select_related('customer')
qs = qs.prefetch_related(self._positions_prefetch(self.request))
qs = qs.select_related('sales_channel').prefetch_related(self._positions_prefetch(self.request))
return qs
def _positions_prefetch(self, request):
@@ -312,6 +325,11 @@ class OrganizerOrderViewSet(OrderViewSetMixin, viewsets.ReadOnlyModelViewSet):
else:
raise PermissionDenied()
def get_serializer_context(self):
ctx = super().get_serializer_context()
ctx['organizer'] = self.request.organizer
return ctx
class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
permission = 'can_view_orders'
@@ -572,8 +590,10 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
return self.retrieve(request, [], **kwargs)
@action(detail=True, methods=['POST'])
@transaction.atomic()
def create_invoice(self, request, **kwargs):
order = self.get_object()
order = Order.objects.select_for_update(of=OF_SELF).get(pk=order.pk)
has_inv = order.invoices.exists() and not (
order.status in (Order.STATUS_PAID, Order.STATUS_PENDING)
and order.invoices.filter(is_cancellation=True).count() >= order.invoices.filter(is_cancellation=False).count()
@@ -900,7 +920,11 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
order_modified.send(sender=serializer.instance.event, order=serializer.instance)
def perform_create(self, serializer):
serializer.save()
try:
serializer.save()
except IntegrityError:
logger.exception("Integrity error while saving order")
raise ValidationError("Integrity error, possibly duplicate submission of same order.")
def perform_destroy(self, instance):
if not instance.testmode:
@@ -1802,17 +1826,14 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
with scopes_disabled():
class InvoiceFilter(FilterSet):
refers = django_filters.CharFilter(method='refers_qs')
number = django_filters.CharFilter(method='nr_qs')
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
number = MultipleCharFilter(field_name='nr', lookup_expr='iexact')
order = MultipleCharFilter(field_name='order', lookup_expr='code__iexact')
def refers_qs(self, queryset, name, value):
return queryset.annotate(
refers_nr=Concat('refers__prefix', 'refers__invoice_no')
).filter(refers_nr__iexact=value)
def nr_qs(self, queryset, name, value):
return queryset.filter(nr__iexact=value)
class Meta:
model = Invoice
fields = ['order', 'number', 'is_cancellation', 'refers', 'locale']
@@ -1898,6 +1919,7 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
return Response(status=204)
@action(detail=True, methods=['POST'])
@transaction.atomic()
def reissue(self, request, **kwargs):
inv = self.get_object()
if inv.canceled:
@@ -1905,9 +1927,10 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
elif inv.shredded:
raise PermissionDenied('The invoice file is no longer stored on the server.')
else:
order = Order.objects.select_for_update(of=OF_SELF).get(pk=inv.order_id)
c = generate_cancellation(inv)
if inv.order.status != Order.STATUS_CANCELED:
inv = generate_invoice(inv.order)
inv = generate_invoice(order)
else:
inv = c
inv.order.log_action(

View File

@@ -24,10 +24,11 @@ from decimal import Decimal
import django_filters
from django.contrib.auth.hashers import make_password
from django.db import transaction
from django.db.models import OuterRef, Subquery, Sum
from django.db.models import OuterRef, Q, Subquery, Sum
from django.db.models.functions import Coalesce
from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django.utils.timezone import now
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import mixins, serializers, status, views, viewsets
@@ -43,18 +44,16 @@ from pretix.api.serializers.organizer import (
CustomerCreateSerializer, CustomerSerializer, DeviceSerializer,
GiftCardSerializer, GiftCardTransactionSerializer, MembershipSerializer,
MembershipTypeSerializer, OrganizerSerializer, OrganizerSettingsSerializer,
SeatingPlanSerializer, TeamAPITokenSerializer, TeamInviteSerializer,
TeamMemberSerializer, TeamSerializer,
SalesChannelSerializer, SeatingPlanSerializer, TeamAPITokenSerializer,
TeamInviteSerializer, TeamMemberSerializer, TeamSerializer,
)
from pretix.base.models import (
Customer, Device, GiftCard, GiftCardTransaction, Membership,
MembershipType, Organizer, SeatingPlan, Team, TeamAPIToken, TeamInvite,
User,
MembershipType, Organizer, SalesChannel, SeatingPlan, Team, TeamAPIToken,
TeamInvite, User,
)
from pretix.base.settings import SETTINGS_AFFECTING_CSS
from pretix.helpers import OF_SELF
from pretix.helpers.dicts import merge_dicts
from pretix.presale.style import regenerate_organizer_css
class OrganizerViewSet(viewsets.ReadOnlyModelViewSet):
@@ -138,11 +137,19 @@ class SeatingPlanViewSet(viewsets.ModelViewSet):
with scopes_disabled():
class GiftCardFilter(FilterSet):
secret = django_filters.CharFilter(field_name='secret', lookup_expr='iexact')
expired = django_filters.BooleanFilter(method='expired_qs')
value = django_filters.NumberFilter(field_name='cached_value')
class Meta:
model = GiftCard
fields = ['secret', 'testmode']
def expired_qs(self, qs, name, value):
if value:
return qs.filter(expires__isnull=False, expires__lt=now())
else:
return qs.filter(Q(expires__isnull=True) | Q(expires__gte=now()))
class GiftCardViewSet(viewsets.ModelViewSet):
serializer_class = GiftCardSerializer
@@ -504,8 +511,6 @@ class OrganizerSettingsView(views.APIView):
k: v for k, v in s.validated_data.items()
}
)
if any(p in s.changed_data for p in SETTINGS_AFFECTING_CSS):
regenerate_organizer_css.apply_async(args=(request.organizer.pk,))
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
'request': request
})
@@ -679,3 +684,68 @@ class MembershipViewSet(viewsets.ModelViewSet):
data=self.request.data,
)
return inst
with scopes_disabled():
class SalesChannelFilter(FilterSet):
class Meta:
model = SalesChannel
fields = ['type', 'identifier']
class SalesChannelViewSet(viewsets.ModelViewSet):
serializer_class = SalesChannelSerializer
queryset = SalesChannel.objects.none()
permission = 'can_change_organizer_settings'
write_permission = 'can_change_organizer_settings'
filter_backends = (DjangoFilterBackend,)
filterset_class = SalesChannelFilter
lookup_field = 'identifier'
lookup_url_kwarg = 'identifier'
lookup_value_regex = r"[a-zA-Z0-9.\-_]+"
def get_queryset(self):
return self.request.organizer.sales_channels.all()
def get_serializer_context(self):
ctx = super().get_serializer_context()
ctx['organizer'] = self.request.organizer
return ctx
@transaction.atomic()
def perform_create(self, serializer):
inst = serializer.save(
organizer=self.request.organizer,
type="api"
)
inst.log_action(
'pretix.saleschannel.created',
user=self.request.user,
auth=self.request.auth,
data=merge_dicts(self.request.data, {'id': inst.pk})
)
@transaction.atomic()
def perform_update(self, serializer):
inst = serializer.save(
type=serializer.instance.type,
identifier=serializer.instance.identifier,
)
inst.log_action(
'pretix.sales_channel.changed',
user=self.request.user,
auth=self.request.auth,
data=self.request.data,
)
return inst
def perform_destroy(self, instance):
if not instance.allow_delete():
raise PermissionDenied("Can only be deleted if unused.")
instance.log_action(
'pretix.saleschannel.deleted',
user=self.request.user,
auth=self.request.auth,
data={'id': instance.pk}
)
instance.delete()

View File

@@ -19,6 +19,8 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import django_filters
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from rest_framework import viewsets
from pretix.api.models import WebHook
@@ -26,11 +28,17 @@ from pretix.api.serializers.webhooks import WebHookSerializer
from pretix.helpers.dicts import merge_dicts
class WebhookFilter(FilterSet):
enabled = django_filters.rest_framework.BooleanFilter()
class WebHookViewSet(viewsets.ModelViewSet):
serializer_class = WebHookSerializer
queryset = WebHook.objects.none()
permission = 'can_change_organizer_settings'
write_permission = 'can_change_organizer_settings'
filter_backends = (DjangoFilterBackend,)
filterset_class = WebhookFilter
def get_queryset(self):
return self.request.organizer.webhooks.prefetch_related('listeners')

View File

@@ -126,6 +126,17 @@ class ParametrizedOrderWebhookEvent(ParametrizedWebhookEvent):
}
class DeletedOrderWebhookEvent(ParametrizedWebhookEvent):
def build_payload(self, logentry: LogEntry):
return {
'notification_id': logentry.pk,
'organizer': logentry.organizer.slug,
'event': logentry.event.slug,
'code': logentry.parsed_data.get("code"),
'action': logentry.action_type,
}
class ParametrizedEventWebhookEvent(ParametrizedWebhookEvent):
def build_payload(self, logentry: LogEntry):
@@ -176,7 +187,7 @@ class ParametrizedItemWebhookEvent(ParametrizedWebhookEvent):
}
class ParametrizedOrderPositionWebhookEvent(ParametrizedOrderWebhookEvent):
class ParametrizedOrderPositionCheckinWebhookEvent(ParametrizedOrderWebhookEvent):
def build_payload(self, logentry: LogEntry):
d = super().build_payload(logentry)
@@ -185,6 +196,7 @@ class ParametrizedOrderPositionWebhookEvent(ParametrizedOrderWebhookEvent):
d['orderposition_id'] = logentry.parsed_data.get('position')
d['orderposition_positionid'] = logentry.parsed_data.get('positionid')
d['checkin_list'] = logentry.parsed_data.get('list')
d['type'] = logentry.parsed_data.get('type')
d['first_checkin'] = logentry.parsed_data.get('first_checkin')
return d
@@ -296,11 +308,15 @@ def register_default_webhook_events(sender, **kwargs):
'pretix.event.order.denied',
_('Order denied'),
),
ParametrizedOrderPositionWebhookEvent(
DeletedOrderWebhookEvent(
'pretix.event.order.deleted',
_('Order deleted'),
),
ParametrizedOrderPositionCheckinWebhookEvent(
'pretix.event.checkin',
_('Ticket checked in'),
),
ParametrizedOrderPositionWebhookEvent(
ParametrizedOrderPositionCheckinWebhookEvent(
'pretix.event.checkin.reverted',
_('Ticket check-in reverted'),
),

View File

@@ -46,7 +46,7 @@ class PretixBaseConfig(AppConfig):
from . import invoice # NOQA
from . import notifications # NOQA
from . import email # NOQA
from .services import auth, checkin, currencies, export, mail, tickets, cart, orderimport, orders, invoices, cleanup, update_check, quotas, notifications, vouchers # NOQA
from .services import auth, checkin, currencies, export, mail, tickets, cart, modelimport, orders, invoices, cleanup, update_check, quotas, notifications, vouchers # NOQA
from .models import _transactions # NOQA
from django.conf import settings

View File

@@ -20,56 +20,83 @@
# <https://www.gnu.org/licenses/>.
#
import logging
import warnings
from collections import OrderedDict
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from pretix.base.signals import register_sales_channels
from pretix.base.signals import (
register_sales_channel_types, register_sales_channels,
)
logger = logging.getLogger(__name__)
_ALL_CHANNELS = None
_ALL_CHANNEL_TYPES = None
class SalesChannel:
class SalesChannelType:
def __repr__(self):
return '<SalesChannel: {}>'.format(self.identifier)
return '<SalesChannelType: {}>'.format(self.identifier)
@property
def identifier(self) -> str:
"""
The internal identifier of this sales channel.
The internal identifier of this sales channel type.
"""
raise NotImplementedError() # NOQA
@property
def verbose_name(self) -> str:
"""
A human-readable name of this sales channel.
A human-readable name of this sales channel type.
"""
raise NotImplementedError() # NOQA
@property
def description(self) -> str:
"""
A human-readable description of this sales channel type.
"""
return ""
@property
def icon(self) -> str:
"""
The name of a Font Awesome icon to represent this channel
This can be:
- The name of a Font Awesome icon to represent this channel type.
- The name of a SVG icon file that is resolvable through the static file system. We recommend to design for a size of 18x14 pixels.
"""
return "circle"
@property
def default_created(self) -> bool:
"""
Indication, if a sales channel of this type should automatically be created for every organizer
"""
return True
@property
def multiple_allowed(self) -> bool:
"""
Indication, if multiple sales channels of this type may exist in the same organizer
"""
return False
@property
def testmode_supported(self) -> bool:
"""
Indication, if a saleschannels supports test mode orders
Indication, if a sales channel of this type supports test mode orders
"""
return True
@property
def payment_restrictions_supported(self) -> bool:
"""
If this property is ``True``, organizers can restrict the usage of payment providers to this sales channel.
If this property is ``True``, organizers can restrict the usage of payment providers to this sales channel type.
Example: pretixPOS provides its own sales channel, ignores the configured payment providers completely and
handles payments locally. Therefor, this property should be set to ``False`` for the pretixPOS sales channel as
Example: pretixPOS provides its own sales channel type, ignores the configured payment providers completely and
handles payments locally. Therefore, this property should be set to ``False`` for the pretixPOS sales channel as
the event organizer cannot restrict the usage of any payment provider through the backend.
"""
return True
@@ -77,8 +104,8 @@ class SalesChannel:
@property
def unlimited_items_per_order(self) -> bool:
"""
If this property is ``True``, purchases made using this sales channel are not limited to the maximum amount of
items defined in the event settings.
If this property is ``True``, purchases made using sales channels of this type are not limited to the maximum
amount of items defined in the event settings.
"""
return False
@@ -96,34 +123,67 @@ class SalesChannel:
"""
return True
@property
def required_event_plugin(self) -> str:
"""
Name of an event plugin that is required for this sales channel to be useful. Defaults to ``None``.
"""
return
def get_all_sales_channels():
global _ALL_CHANNELS
if _ALL_CHANNELS:
return _ALL_CHANNELS
def get_all_sales_channel_types():
from pretix.base.signals import register_sales_channel_types
global _ALL_CHANNEL_TYPES
if _ALL_CHANNEL_TYPES:
return _ALL_CHANNEL_TYPES
channels = []
for recv, ret in register_sales_channels.send(None):
for recv, ret in register_sales_channel_types.send(None):
if isinstance(ret, (list, tuple)):
channels += ret
else:
channels.append(ret)
for recv, ret in register_sales_channels.send(None): # todo: remove me
if isinstance(ret, (list, tuple)):
channels += ret
else:
channels.append(ret)
channels.sort(key=lambda c: c.identifier)
_ALL_CHANNELS = OrderedDict([(c.identifier, c) for c in channels])
if 'web' in _ALL_CHANNELS:
_ALL_CHANNELS.move_to_end('web', last=False)
return _ALL_CHANNELS
_ALL_CHANNEL_TYPES = OrderedDict([(c.identifier, c) for c in channels])
if 'web' in _ALL_CHANNEL_TYPES:
_ALL_CHANNEL_TYPES.move_to_end('web', last=False)
return _ALL_CHANNEL_TYPES
class WebshopSalesChannel(SalesChannel):
def get_all_sales_channels():
# TODO: remove me
warnings.warn('Using get_all_sales_channels() is no longer appropriate, use get_al_sales_channel_types() instead.',
DeprecationWarning, stacklevel=2)
return get_all_sales_channel_types()
class WebshopSalesChannelType(SalesChannelType):
identifier = "web"
verbose_name = _('Online shop')
icon = "globe"
@receiver(register_sales_channels, dispatch_uid="base_register_default_sales_channels")
class ApiSalesChannelType(SalesChannelType):
identifier = "api"
verbose_name = _('API')
description = _('API sales channels come with no built-in functionality, but may be used for custom integrations.')
icon = "exchange"
default_created = False
multiple_allowed = True
SalesChannel = SalesChannelType # TODO: remove me
@receiver(register_sales_channel_types, dispatch_uid="base_register_default_sales_channel_types")
def base_sales_channels(sender, **kwargs):
return (
WebshopSalesChannel(),
WebshopSalesChannelType(),
ApiSalesChannelType(),
)

View File

@@ -19,10 +19,7 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import inspect
import logging
from datetime import timedelta
from decimal import Decimal
from itertools import groupby
from smtplib import SMTPResponseException
from typing import TypeVar
@@ -33,21 +30,21 @@ from django.core.mail.backends.smtp import EmailBackend
from django.db.models import Count
from django.dispatch import receiver
from django.template.loader import get_template
from django.utils.formats import date_format
from django.utils.timezone import now
from django.utils.translation import get_language, gettext_lazy as _
from pretix.base.i18n import (
LazyCurrencyNumber, LazyDate, LazyExpiresDate, LazyNumber,
)
from pretix.base.models import Event
from pretix.base.reldate import RelativeDateWrapper
from pretix.base.settings import PERSON_NAME_SCHEMES, get_name_parts_localized
from pretix.base.signals import (
register_html_mail_renderers, register_mail_placeholders,
)
from pretix.base.signals import register_html_mail_renderers
from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.base.services.placeholders import ( # noqa
get_available_placeholders, PlaceholderContext
)
from pretix.base.services.placeholders import ( # noqa
BaseTextPlaceholder as BaseMailTextPlaceholder,
SimpleFunctionalTextPlaceholder as SimpleFunctionalMailTextPlaceholder,
)
from pretix.base.settings import get_name_parts_localized # noqa
logger = logging.getLogger('pretix.base.email')
T = TypeVar("T", bound=EmailBackend)
@@ -192,7 +189,7 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
tpl = get_template(self.template_name)
body_html = tpl.render(htmlctx)
inliner = css_inline.CSSInliner(remove_style_tags=True)
inliner = css_inline.CSSInliner(keep_style_tags=False)
body_html = inliner.inline(body_html)
return body_html
@@ -217,495 +214,5 @@ def base_renderers(sender, **kwargs):
return [ClassicMailRenderer, UnembellishedMailRenderer]
class BaseMailTextPlaceholder:
"""
This is the base class for for all email text placeholders.
"""
@property
def required_context(self):
"""
This property should return a list of all attribute names that need to be
contained in the base context so that this placeholder is available. By default,
it returns a list containing the string "event".
"""
return ["event"]
@property
def identifier(self):
"""
This should return the identifier of this placeholder in the email.
"""
raise NotImplementedError()
def render(self, context):
"""
This method is called to generate the actual text that is being
used in the email. You will be passed a context dictionary with the
base context attributes specified in ``required_context``. You are
expected to return a plain-text string.
"""
raise NotImplementedError()
def render_sample(self, event):
"""
This method is called to generate a text to be used in email previews.
This may only depend on the event.
"""
raise NotImplementedError()
class SimpleFunctionalMailTextPlaceholder(BaseMailTextPlaceholder):
def __init__(self, identifier, args, func, sample):
self._identifier = identifier
self._args = args
self._func = func
self._sample = sample
@property
def identifier(self):
return self._identifier
@property
def required_context(self):
return self._args
def render(self, context):
return self._func(**{k: context[k] for k in self._args})
def render_sample(self, event):
if callable(self._sample):
return self._sample(event)
else:
return self._sample
def get_available_placeholders(event, base_parameters):
if 'order' in base_parameters:
base_parameters.append('invoice_address')
base_parameters.append('position_or_address')
params = {}
for r, val in register_mail_placeholders.send(sender=event):
if not isinstance(val, (list, tuple)):
val = [val]
for v in val:
if all(rp in base_parameters for rp in v.required_context):
params[v.identifier] = v
return params
def get_email_context(**kwargs):
from pretix.base.models import InvoiceAddress
event = kwargs['event']
if 'position' in kwargs:
kwargs.setdefault("position_or_address", kwargs['position'])
if 'order' in kwargs:
try:
if not kwargs.get('invoice_address'):
kwargs['invoice_address'] = kwargs['order'].invoice_address
except InvoiceAddress.DoesNotExist:
kwargs['invoice_address'] = InvoiceAddress(order=kwargs['order'])
finally:
kwargs.setdefault("position_or_address", kwargs['invoice_address'])
ctx = {}
for r, val in register_mail_placeholders.send(sender=event):
if not isinstance(val, (list, tuple)):
val = [val]
for v in val:
if all(rp in kwargs for rp in v.required_context):
try:
ctx[v.identifier] = v.render(kwargs)
except:
ctx[v.identifier] = '(error)'
logger.exception(f'Failed to process email placeholder {v.identifier}.')
return ctx
def _placeholder_payments(order, payments):
d = []
for payment in payments:
if 'payment' in inspect.signature(payment.payment_provider.order_pending_mail_render).parameters:
d.append(str(payment.payment_provider.order_pending_mail_render(order, payment)))
else:
d.append(str(payment.payment_provider.order_pending_mail_render(order)))
d = [line for line in d if line.strip()]
if d:
return '\n\n'.join(d)
else:
return ''
def get_best_name(position_or_address, parts=False):
"""
Return the best name we got for either an invoice address or an order position, falling back to the respective other
"""
from pretix.base.models import InvoiceAddress, OrderPosition
if isinstance(position_or_address, InvoiceAddress):
if position_or_address.name:
return position_or_address.name_parts if parts else position_or_address.name
elif position_or_address.order:
position_or_address = position_or_address.order.positions.exclude(attendee_name_cached="").exclude(attendee_name_cached__isnull=True).first()
if isinstance(position_or_address, OrderPosition):
if position_or_address.attendee_name:
return position_or_address.attendee_name_parts if parts else position_or_address.attendee_name
elif position_or_address.order:
try:
return position_or_address.order.invoice_address.name_parts if parts else position_or_address.order.invoice_address.name
except InvoiceAddress.DoesNotExist:
pass
return {} if parts else ""
@receiver(register_mail_placeholders, dispatch_uid="pretixbase_register_mail_placeholders")
def base_placeholders(sender, **kwargs):
from pretix.multidomain.urlreverse import build_absolute_uri
ph = [
SimpleFunctionalMailTextPlaceholder(
'event', ['event'], lambda event: event.name, lambda event: event.name
),
SimpleFunctionalMailTextPlaceholder(
'event', ['event_or_subevent'], lambda event_or_subevent: event_or_subevent.name,
lambda event_or_subevent: event_or_subevent.name
),
SimpleFunctionalMailTextPlaceholder(
'event_slug', ['event'], lambda event: event.slug, lambda event: event.slug
),
SimpleFunctionalMailTextPlaceholder(
'code', ['order'], lambda order: order.code, 'F8VVL'
),
SimpleFunctionalMailTextPlaceholder(
'total', ['order'], lambda order: LazyNumber(order.total), lambda event: LazyNumber(Decimal('42.23'))
),
SimpleFunctionalMailTextPlaceholder(
'currency', ['event'], lambda event: event.currency, lambda event: event.currency
),
SimpleFunctionalMailTextPlaceholder(
'order_email', ['order'], lambda order: order.email, 'john@example.org'
),
SimpleFunctionalMailTextPlaceholder(
'invoice_number', ['invoice'],
lambda invoice: invoice.full_invoice_no,
f'{sender.settings.invoice_numbers_prefix or (sender.slug.upper() + "-")}00000'
),
SimpleFunctionalMailTextPlaceholder(
'refund_amount', ['event_or_subevent', 'refund_amount'],
lambda event_or_subevent, refund_amount: LazyCurrencyNumber(refund_amount, event_or_subevent.currency),
lambda event_or_subevent: LazyCurrencyNumber(Decimal('42.23'), event_or_subevent.currency)
),
SimpleFunctionalMailTextPlaceholder(
'pending_sum', ['event', 'pending_sum'],
lambda event, pending_sum: LazyCurrencyNumber(pending_sum, event.currency),
lambda event: LazyCurrencyNumber(Decimal('42.23'), event.currency)
),
SimpleFunctionalMailTextPlaceholder(
'total_with_currency', ['event', 'order'], lambda event, order: LazyCurrencyNumber(order.total,
event.currency),
lambda event: LazyCurrencyNumber(Decimal('42.23'), event.currency)
),
SimpleFunctionalMailTextPlaceholder(
'expire_date', ['event', 'order'], lambda event, order: LazyExpiresDate(order.expires.astimezone(event.timezone)),
lambda event: LazyDate(now() + timedelta(days=15))
),
SimpleFunctionalMailTextPlaceholder(
'url', ['order', 'event'], lambda order, event: build_absolute_uri(
event,
'presale:event.order.open', kwargs={
'order': order.code,
'secret': order.secret,
'hash': order.email_confirm_hash()
}
), lambda event: build_absolute_uri(
event,
'presale:event.order.open', kwargs={
'order': 'F8VVL',
'secret': '6zzjnumtsx136ddy',
'hash': '98kusd8ofsj8dnkd'
}
),
),
SimpleFunctionalMailTextPlaceholder(
'url_info_change', ['order', 'event'], lambda order, event: build_absolute_uri(
event,
'presale:event.order.modify', kwargs={
'order': order.code,
'secret': order.secret,
}
), lambda event: build_absolute_uri(
event,
'presale:event.order.modify', kwargs={
'order': 'F8VVL',
'secret': '6zzjnumtsx136ddy',
}
),
),
SimpleFunctionalMailTextPlaceholder(
'url_products_change', ['order', 'event'], lambda order, event: build_absolute_uri(
event,
'presale:event.order.change', kwargs={
'order': order.code,
'secret': order.secret,
}
), lambda event: build_absolute_uri(
event,
'presale:event.order.change', kwargs={
'order': 'F8VVL',
'secret': '6zzjnumtsx136ddy',
}
),
),
SimpleFunctionalMailTextPlaceholder(
'url_cancel', ['order', 'event'], lambda order, event: build_absolute_uri(
event,
'presale:event.order.cancel', kwargs={
'order': order.code,
'secret': order.secret,
}
), lambda event: build_absolute_uri(
event,
'presale:event.order.cancel', kwargs={
'order': 'F8VVL',
'secret': '6zzjnumtsx136ddy',
}
),
),
SimpleFunctionalMailTextPlaceholder(
'url', ['event', 'position'], lambda event, position: build_absolute_uri(
event,
'presale:event.order.position',
kwargs={
'order': position.order.code,
'secret': position.web_secret,
'position': position.positionid
}
),
lambda event: build_absolute_uri(
event,
'presale:event.order.position', kwargs={
'order': 'F8VVL',
'secret': '6zzjnumtsx136ddy',
'position': '123'
}
),
),
SimpleFunctionalMailTextPlaceholder(
'order_modification_deadline_date_and_time', ['order', 'event'],
lambda order, event:
date_format(order.modify_deadline.astimezone(event.timezone), 'SHORT_DATETIME_FORMAT')
if order.modify_deadline
else '',
lambda event: date_format(
event.settings.get(
'last_order_modification_date', as_type=RelativeDateWrapper
).datetime(event).astimezone(event.timezone),
'SHORT_DATETIME_FORMAT'
) if event.settings.get('last_order_modification_date') else '',
),
SimpleFunctionalMailTextPlaceholder(
'event_location', ['event_or_subevent'], lambda event_or_subevent: str(event_or_subevent.location or ''),
lambda event: str(event.location or ''),
),
SimpleFunctionalMailTextPlaceholder(
'event_admission_time', ['event_or_subevent'],
lambda event_or_subevent:
date_format(event_or_subevent.date_admission.astimezone(event_or_subevent.timezone), 'TIME_FORMAT')
if event_or_subevent.date_admission
else '',
lambda event: date_format(event.date_admission.astimezone(event.timezone), 'TIME_FORMAT') if event.date_admission else '',
),
SimpleFunctionalMailTextPlaceholder(
'subevent', ['waiting_list_entry', 'event'],
lambda waiting_list_entry, event: str(waiting_list_entry.subevent or event),
lambda event: str(event if not event.has_subevents or not event.subevents.exists() else event.subevents.first())
),
SimpleFunctionalMailTextPlaceholder(
'subevent_date_from', ['waiting_list_entry', 'event'],
lambda waiting_list_entry, event: (waiting_list_entry.subevent or event).get_date_from_display(),
lambda event: (event if not event.has_subevents or not event.subevents.exists() else event.subevents.first()).get_date_from_display()
),
SimpleFunctionalMailTextPlaceholder(
'url_remove', ['waiting_list_voucher', 'event'],
lambda waiting_list_voucher, event: build_absolute_uri(
event, 'presale:event.waitinglist.remove'
) + '?voucher=' + waiting_list_voucher.code,
lambda event: build_absolute_uri(
event,
'presale:event.waitinglist.remove',
) + '?voucher=68CYU2H6ZTP3WLK5',
),
SimpleFunctionalMailTextPlaceholder(
'url', ['waiting_list_voucher', 'event'],
lambda waiting_list_voucher, event: build_absolute_uri(
event, 'presale:event.redeem'
) + '?voucher=' + waiting_list_voucher.code,
lambda event: build_absolute_uri(
event,
'presale:event.redeem',
) + '?voucher=68CYU2H6ZTP3WLK5',
),
SimpleFunctionalMailTextPlaceholder(
'invoice_name', ['invoice_address'], lambda invoice_address: invoice_address.name or '',
_('John Doe')
),
SimpleFunctionalMailTextPlaceholder(
'invoice_company', ['invoice_address'], lambda invoice_address: invoice_address.company or '',
_('Sample Corporation')
),
SimpleFunctionalMailTextPlaceholder(
'orders', ['event', 'orders'], lambda event, orders: '\n' + '\n\n'.join(
'* {} - {}'.format(
order.full_code,
build_absolute_uri(event, 'presale:event.order.open', kwargs={
'event': event.slug,
'organizer': event.organizer.slug,
'order': order.code,
'secret': order.secret,
'hash': order.email_confirm_hash(),
}),
)
for order in orders
), lambda event: '\n' + '\n\n'.join(
'* {} - {}'.format(
'{}-{}'.format(event.slug.upper(), order['code']),
build_absolute_uri(event, 'presale:event.order.open', kwargs={
'event': event.slug,
'organizer': event.organizer.slug,
'order': order['code'],
'secret': order['secret'],
'hash': order['hash'],
}),
)
for order in [
{'code': 'F8VVL', 'secret': '6zzjnumtsx136ddy', 'hash': 'abcdefghi'},
{'code': 'HIDHK', 'secret': '98kusd8ofsj8dnkd', 'hash': 'jklmnopqr'},
{'code': 'OPKSB', 'secret': '09pjdksflosk3njd', 'hash': 'stuvwxy2z'}
]
),
),
SimpleFunctionalMailTextPlaceholder(
'hours', ['event', 'waiting_list_entry'], lambda event, waiting_list_entry:
event.settings.waiting_list_hours,
lambda event: event.settings.waiting_list_hours
),
SimpleFunctionalMailTextPlaceholder(
'product', ['waiting_list_entry'], lambda waiting_list_entry: waiting_list_entry.item.name,
_('Sample Admission Ticket')
),
SimpleFunctionalMailTextPlaceholder(
'code', ['waiting_list_voucher'], lambda waiting_list_voucher: waiting_list_voucher.code,
'68CYU2H6ZTP3WLK5'
),
SimpleFunctionalMailTextPlaceholder(
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
'voucher_list', ['voucher_list'], lambda voucher_list: ' \n'.join(voucher_list),
' 68CYU2H6ZTP3WLK5\n 7MB94KKPVEPSMVF2'
),
SimpleFunctionalMailTextPlaceholder(
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
'voucher_url_list', ['event', 'voucher_list'],
lambda event, voucher_list: ' \n'.join([
build_absolute_uri(
event, 'presale:event.redeem'
) + '?voucher=' + c
for c in voucher_list
]),
lambda event: ' \n'.join([
build_absolute_uri(
event, 'presale:event.redeem'
) + '?voucher=' + c
for c in ['68CYU2H6ZTP3WLK5', '7MB94KKPVEPSMVF2']
]),
),
SimpleFunctionalMailTextPlaceholder(
'url', ['event', 'voucher_list'], lambda event, voucher_list: build_absolute_uri(event, 'presale:event.index', kwargs={
'event': event.slug,
'organizer': event.organizer.slug,
}), lambda event: build_absolute_uri(event, 'presale:event.index', kwargs={
'event': event.slug,
'organizer': event.organizer.slug,
})
),
SimpleFunctionalMailTextPlaceholder(
'name', ['name'], lambda name: name,
_('John Doe')
),
SimpleFunctionalMailTextPlaceholder(
'comment', ['comment'], lambda comment: comment,
_('An individual text with a reason can be inserted here.'),
),
SimpleFunctionalMailTextPlaceholder(
'payment_info', ['order', 'payments'], _placeholder_payments,
_('The amount has been charged to your card.'),
),
SimpleFunctionalMailTextPlaceholder(
'payment_info', ['payment_info'], lambda payment_info: payment_info,
_('Please transfer money to this bank account: 9999-9999-9999-9999'),
),
SimpleFunctionalMailTextPlaceholder(
'attendee_name', ['position'], lambda position: position.attendee_name,
_('John Doe'),
),
SimpleFunctionalMailTextPlaceholder(
'positionid', ['position'], lambda position: str(position.positionid),
'1'
),
SimpleFunctionalMailTextPlaceholder(
'name', ['position_or_address'],
get_best_name,
_('John Doe'),
),
]
name_scheme = PERSON_NAME_SCHEMES[sender.settings.name_scheme]
if "concatenation_for_salutation" in name_scheme:
concatenation_for_salutation = name_scheme["concatenation_for_salutation"]
else:
concatenation_for_salutation = name_scheme["concatenation"]
ph.append(SimpleFunctionalMailTextPlaceholder(
"name_for_salutation", ["waiting_list_entry"],
lambda waiting_list_entry: concatenation_for_salutation(waiting_list_entry.name_parts),
_("Mr Doe"),
))
ph.append(SimpleFunctionalMailTextPlaceholder(
"name", ["waiting_list_entry"],
lambda waiting_list_entry: waiting_list_entry.name or "",
_("Mr Doe"),
))
ph.append(SimpleFunctionalMailTextPlaceholder(
"name_for_salutation", ["position_or_address"],
lambda position_or_address: concatenation_for_salutation(get_best_name(position_or_address, parts=True)),
_("Mr Doe"),
))
for f, l, w in name_scheme['fields']:
if f == 'full_name':
continue
ph.append(SimpleFunctionalMailTextPlaceholder(
'name_%s' % f, ['waiting_list_entry'], lambda waiting_list_entry, f=f: get_name_parts_localized(waiting_list_entry.name_parts, f),
name_scheme['sample'][f]
))
ph.append(SimpleFunctionalMailTextPlaceholder(
'attendee_name_%s' % f, ['position'], lambda position, f=f: get_name_parts_localized(position.attendee_name_parts, f),
name_scheme['sample'][f]
))
ph.append(SimpleFunctionalMailTextPlaceholder(
'name_%s' % f, ['position_or_address'],
lambda position_or_address, f=f: get_name_parts_localized(get_best_name(position_or_address, parts=True), f),
name_scheme['sample'][f]
))
for k, v in sender.meta_data.items():
ph.append(SimpleFunctionalMailTextPlaceholder(
'meta_%s' % k, ['event'], lambda event, k=k: event.meta_data[k],
v
))
ph.append(SimpleFunctionalMailTextPlaceholder(
'meta_%s' % k, ['event_or_subevent'], lambda event_or_subevent, k=k: event_or_subevent.meta_data[k],
v
))
return ph
return PlaceholderContext(**kwargs).render_all()

View File

@@ -207,10 +207,13 @@ class ListExporter(BaseExporter):
def get_filename(self):
return 'export'
def get_csv_encoding(self):
return 'utf-8'
def _render_csv(self, form_data, output_file=None, **kwargs):
if output_file:
if 'b' in output_file.mode:
output_file = io.TextIOWrapper(output_file, encoding='utf-8', newline='')
output_file = io.TextIOWrapper(output_file, encoding=self.get_csv_encoding(), errors='replace', newline='')
writer = csv.writer(output_file, **kwargs)
total = 0
counter = 0
@@ -246,7 +249,7 @@ class ListExporter(BaseExporter):
if counter % max(10, total // 100) == 0:
self.progress_callback(counter / total * 100)
writer.writerow(line)
return self.get_filename() + '.csv', 'text/csv', output.getvalue().encode("utf-8")
return self.get_filename() + '.csv', 'text/csv', output.getvalue().encode(self.get_csv_encoding(), errors='replace')
def prepare_xlsx_sheet(self, ws):
pass
@@ -256,7 +259,7 @@ class ListExporter(BaseExporter):
ws = wb.create_sheet()
self.prepare_xlsx_sheet(ws)
try:
ws.title = str(self.verbose_name)
ws.title = str(self.verbose_name)[:30]
except:
pass
total = 0
@@ -374,7 +377,7 @@ class MultiSheetListExporter(ListExporter):
wb = SafeWorkbook(write_only=True)
n_sheets = len(self.sheets)
for i_sheet, (s, l) in enumerate(self.sheets):
ws = wb.create_sheet(str(l))
ws = wb.create_sheet(str(l)[:30])
if hasattr(self, 'prepare_xlsx_sheet_' + s):
getattr(self, 'prepare_xlsx_sheet_' + s)(ws)

View File

@@ -39,10 +39,12 @@ from zipfile import ZipFile
from django import forms
from django.dispatch import receiver
from django.urls import reverse
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from pretix.base.models import QuestionAnswer
from ...control.forms.widgets import Select2
from ..exporter import BaseExporter
from ..signals import register_data_exporters
@@ -56,7 +58,7 @@ class AnswerFilesExporter(BaseExporter):
@property
def export_form_fields(self):
return OrderedDict(
d = OrderedDict(
[
('questions',
forms.ModelMultipleChoiceField(
@@ -69,11 +71,32 @@ class AnswerFilesExporter(BaseExporter):
)),
]
)
if self.event.has_subevents:
d['subevent'] = forms.ModelChoiceField(
label=pgettext_lazy('subevent', 'Date'),
queryset=self.event.subevents.all(),
required=False,
empty_label=pgettext_lazy('subevent', 'All dates')
)
d['subevent'].widget = Select2(
attrs={
'data-model-select2': 'event',
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
'event': self.event.slug,
'organizer': self.event.organizer.slug,
}),
'data-placeholder': pgettext_lazy('subevent', 'All dates')
}
)
d['subevent'].widget.choices = d['subevent'].choices
return d
def render(self, form_data: dict):
qs = QuestionAnswer.objects.filter(
orderposition__order__event=self.event,
).select_related('orderposition', 'orderposition__order', 'question')
if form_data.get('subevent'):
qs = qs.filter(orderposition__subevent=form_data.get('subevent'))
if form_data.get('questions'):
qs = qs.filter(question__in=form_data['questions'])
with tempfile.TemporaryDirectory() as d:

View File

@@ -116,15 +116,29 @@ class DekodiNREIExporter(BaseExporter):
'PTNo15': p.full_id or '',
})
elif p.provider and p.provider.startswith('stripe'):
src = p.info_data.get("source", p.info_data)
pi = p.info_data or {}
try:
if "latest_charge" in pi and isinstance(pi.get("latest_charge"), dict):
details = pi["latest_charge"]["payment_method_details"]
card = details.get("card", {})
elif pi.get("charges") and pi["charges"]["data"]:
details = pi["charges"]["data"][0].get("payment_method_details", {})
card = details.get("card", {})
else:
details = pi["source"]
card = pi["source"]["card"]
except:
details = {}
card = {}
payments.append({
'PTID': '81',
'PTN': 'Stripe',
'PTNo1': p.info_data.get("id") or '',
'PTNo5': src.get("card", {}).get("last4") or '',
'PTNo1': pi.get("id") or '',
'PTNo5': card.get("last4", ""),
'PTNo7': round(float(p.amount), 2) or '',
'PTNo8': str(self.event.currency) or '',
'PTNo10': src.get('owner', {}).get('verified_name') or src.get('owner', {}).get('name') or '',
'PTNo10': details.get('owner', {}).get('verified_name') or details.get('owner', {}).get('name') or '',
'PTNo15': p.full_id or '',
})
else:

View File

@@ -86,6 +86,7 @@ class InvoiceExporterMixin:
('', _('All payment providers')),
] + [
(k, v.verbose_name) for k, v in self.event.get_payment_providers().items()
if not v.is_meta
],
required=False,
help_text=_('Only include invoices for orders that have at least one payment attempt '

View File

@@ -27,7 +27,6 @@ from openpyxl.styles import Alignment
from openpyxl.utils import get_column_letter
from ...helpers.safe_openpyxl import SafeCell
from ..channels import get_all_sales_channels
from ..exporter import ListExporter
from ..models import ItemMetaValue, ItemVariation, ItemVariationMetaValue
from ..signals import register_data_exporters
@@ -53,7 +52,7 @@ class ItemDataExporter(ListExporter):
def iterate_list(self, form_data):
locales = self.event.settings.locales
scs = get_all_sales_channels()
scs = self.organizer.sales_channels.all()
header = [
_("Product ID"),
_("Variation ID"),
@@ -141,9 +140,15 @@ class ItemDataExporter(ListExporter):
row.append(i.name.localize(l))
for l in locales:
row.append(v.value.localize(l))
sales_channels = list(scs)
if not i.all_sales_channels:
sales_channels = [s for s in sales_channels if s.identifier in (p.identifier for p in i.limit_sales_channels.all())]
if not v.all_sales_channels:
sales_channels = [s for s in sales_channels if s.identifier in (p.identifier for p in v.limit_sales_channels.all())]
row += [
_("Yes") if i.active and v.active else "",
", ".join([str(sn.verbose_name) for s, sn in scs.items() if s in i.sales_channels and s in v.sales_channels]),
", ".join([str(sn.label) for sn in sales_channels]),
v.default_price or i.default_price,
_("Yes") if i.free_price else "",
str(i.tax_rule) if i.tax_rule else "",
@@ -186,9 +191,12 @@ class ItemDataExporter(ListExporter):
row.append(i.name.localize(l))
for l in locales:
row.append("")
sales_channels = list(scs)
if not i.all_sales_channels:
sales_channels = [s for s in sales_channels if s.identifier in (p.identifier for p in i.limit_sales_channels.all())]
row += [
_("Yes") if i.active else "",
", ".join([str(sn.verbose_name) for s, sn in scs.items() if s in i.sales_channels]),
", ".join([str(sn.label) for sn in sales_channels]),
i.default_price,
_("Yes") if i.free_price else "",
str(i.tax_rule) if i.tax_rule else "",

View File

@@ -54,6 +54,7 @@ class JSONExporter(BaseExporter):
'import in third-party systems.')
def render(self, form_data):
all_sales_channels = self.event.organizer.sales_channels.all()
jo = {
'event': {
'name': str(self.event.name),
@@ -85,7 +86,7 @@ class JSONExporter(BaseExporter):
'admission': item.admission,
'personalized': item.personalized,
'active': item.active,
'sales_channels': item.sales_channels,
'sales_channels': [c.identifier for c in (all_sales_channels if item.all_sales_channels else item.limit_sales_channels.all())],
'description': str(item.description),
'available_from': item.available_from,
'available_until': item.available_until,
@@ -114,7 +115,9 @@ class JSONExporter(BaseExporter):
'checkin_text': variation.checkin_text,
'require_approval': variation.require_approval,
'require_membership': variation.require_membership,
'sales_channels': variation.sales_channels,
'sales_channels': [
c.identifier for c in (all_sales_channels if variation.all_sales_channels else variation.limit_sales_channels.all())
],
'available_from': variation.available_from,
'available_until': variation.available_until,
'hide_without_voucher': variation.hide_without_voucher,
@@ -122,6 +125,7 @@ class JSONExporter(BaseExporter):
} for variation in item.variations.all()
]
} for item in self.event.items.select_related('tax_rule').prefetch_related(
'limit_sales_channels',
Prefetch(
'meta_values',
ItemMetaValue.objects.select_related('property'),
@@ -130,6 +134,7 @@ class JSONExporter(BaseExporter):
Prefetch(
'variations',
queryset=ItemVariation.objects.prefetch_related(
'limit_sales_channels',
Prefetch(
'meta_values',
ItemVariationMetaValue.objects.select_related('property'),
@@ -167,7 +172,7 @@ class JSONExporter(BaseExporter):
'require_approval': order.require_approval,
'checkin_attention': order.checkin_attention,
'checkin_text': order.checkin_text,
'sales_channel': order.sales_channel,
'sales_channel': order.sales_channel.identifier,
'expires': order.expires,
'datetime': order.datetime,
'fees': [

View File

@@ -32,11 +32,12 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under the License.
from collections import OrderedDict
from collections import OrderedDict, defaultdict
from decimal import Decimal
from zoneinfo import ZoneInfo
from django import forms
from django.conf import settings
from django.db.models import (
Case, CharField, Count, DateTimeField, F, IntegerField, Max, Min, OuterRef,
Q, Subquery, Sum, When,
@@ -54,7 +55,7 @@ from openpyxl.comments import Comment
from openpyxl.styles import Font, PatternFill
from pretix.base.models import (
GiftCard, GiftCardTransaction, Invoice, InvoiceAddress, Order,
Checkin, GiftCard, GiftCardTransaction, Invoice, InvoiceAddress, Order,
OrderPosition, Question,
)
from pretix.base.models.orders import (
@@ -209,7 +210,7 @@ class OrderListExporter(MultiSheetListExporter):
return qs.annotate(**annotations).filter(**filters)
return qs
def iterate_orders(self, form_data: dict):
def orders_qs(self, form_data):
p_date = OrderPayment.objects.filter(
order=OuterRef('pk'),
state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED),
@@ -250,11 +251,15 @@ class OrderListExporter(MultiSheetListExporter):
if form_data['paid_only']:
qs = qs.filter(status=Order.STATUS_PAID)
return qs
def iterate_orders(self, form_data: dict):
qs = self.orders_qs(form_data)
tax_rates = self._get_all_tax_rates(qs)
headers = [
_('Event slug'), _('Order code'), _('Order total'), _('Status'), _('Email'), _('Phone number'),
_('Order date'), _('Order time'), _('Company'), _('Name'),
_('Event slug'), _('Event name'), _('Order code'), _('Order total'), _('Status'), _('Email'),
_('Phone number'), _('Order date'), _('Order time'), _('Company'), _('Name'),
]
name_scheme = PERSON_NAME_SCHEMES[self.event.settings.name_scheme] if not self.is_multievent else None
if name_scheme and len(name_scheme['fields']) > 1:
@@ -331,6 +336,7 @@ class OrderListExporter(MultiSheetListExporter):
row = [
self.event_object_cache[order.event_id].slug,
str(self.event_object_cache[order.event_id].name),
order.code,
order.total,
order.get_extended_status_display(),
@@ -406,7 +412,7 @@ class OrderListExporter(MultiSheetListExporter):
row += self.event_object_cache[order.event_id].meta_data.values()
yield row
def iterate_fees(self, form_data: dict):
def fees_qs(self, form_data):
p_providers = OrderPayment.objects.filter(
order=OuterRef('order'),
state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED,
@@ -425,9 +431,14 @@ class OrderListExporter(MultiSheetListExporter):
qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False)
qs = self._date_filter(qs, form_data, rel='order__')
return qs
def iterate_fees(self, form_data: dict):
qs = self.fees_qs(form_data)
headers = [
_('Event slug'),
_('Event name'),
_('Order code'),
_('Status'),
_('Email'),
@@ -464,6 +475,7 @@ class OrderListExporter(MultiSheetListExporter):
tz = ZoneInfo(order.event.settings.timezone)
row = [
self.event_object_cache[order.event_id].slug,
str(self.event_object_cache[order.event_id].name),
order.code,
_("canceled") if op.canceled else order.get_extended_status_display(),
order.email,
@@ -506,7 +518,19 @@ class OrderListExporter(MultiSheetListExporter):
row += self.event_object_cache[order.event_id].meta_data.values()
yield row
def positions_qs(self, form_data: dict):
qs = OrderPosition.all.filter(
order__event__in=self.events,
)
if form_data['paid_only']:
qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False)
qs = self._date_filter(qs, form_data, rel='order__')
return qs
def iterate_positions(self, form_data: dict):
base_qs = self.positions_qs(form_data)
p_providers = OrderPayment.objects.filter(
order=OuterRef('order'),
state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED,
@@ -516,27 +540,37 @@ class OrderListExporter(MultiSheetListExporter):
).values(
'm'
).order_by()
base_qs = OrderPosition.all.filter(
order__event__in=self.events,
)
qs = base_qs.annotate(
payment_providers=Subquery(p_providers, output_field=CharField()),
checked_in_lists=Subquery(
Checkin.objects.filter(
successful=True,
type=Checkin.TYPE_ENTRY,
position=OuterRef("pk"),
).order_by().values("position").annotate(
c=GroupConcat(
"list__name",
# These appear not to work properly on SQLite. Well, we don't support SQLite outside testing
# anyways.
ordered='sqlite' not in settings.DATABASES['default']['ENGINE'],
distinct='sqlite' not in settings.DATABASES['default']['ENGINE'],
delimiter=", "
)
).values("c")
),
).select_related(
'order', 'order__invoice_address', 'order__customer', 'item', 'variation',
'voucher', 'tax_rule'
'voucher', 'tax_rule', 'addon_to',
).prefetch_related(
'subevent', 'subevent__meta_values',
'answers', 'answers__question', 'answers__options'
)
if form_data['paid_only']:
qs = qs.filter(order__status=Order.STATUS_PAID, canceled=False)
qs = self._date_filter(qs, form_data, rel='order__')
has_subevents = self.events.filter(has_subevents=True).exists()
headers = [
_('Event slug'),
_('Event name'),
_('Order code'),
_('Position ID'),
_('Status'),
@@ -585,13 +619,13 @@ class OrderListExporter(MultiSheetListExporter):
_('Valid until'),
_('Order comment'),
_('Follow-up date'),
_('Add-on to position ID'),
]
questions = list(Question.objects.filter(event__in=self.events))
options = {}
options = defaultdict(list)
for q in questions:
if q.type == Question.TYPE_CHOICE_MULTIPLE:
options[q.pk] = []
if form_data['group_multiple_choice']:
for o in q.options.all():
options[q.pk].append(o)
@@ -601,6 +635,9 @@ class OrderListExporter(MultiSheetListExporter):
headers.append(str(q.question) + ' ' + str(o.answer))
options[q.pk].append(o)
else:
if q.type == Question.TYPE_CHOICE:
for o in q.options.all():
options[q.pk].append(o)
headers.append(str(q.question))
headers += [
_('Company'),
@@ -616,9 +653,11 @@ class OrderListExporter(MultiSheetListExporter):
_('VAT ID'),
]
headers += [
_('Sales channel'), _('Order locale'),
_('Sales channel'),
_('Order locale'),
_('E-mail address verified'),
_('External customer ID'),
_('Check-in lists'),
_('Payment providers'),
]
@@ -638,6 +677,7 @@ class OrderListExporter(MultiSheetListExporter):
tz = ZoneInfo(self.event_object_cache[order.event_id].settings.timezone)
row = [
self.event_object_cache[order.event_id].slug,
str(self.event_object_cache[order.event_id].name),
order.code,
op.positionid,
_("canceled") if op.canceled else order.get_extended_status_display(),
@@ -705,11 +745,12 @@ class OrderListExporter(MultiSheetListExporter):
]
row.append(order.comment)
row.append(order.custom_followup_at.strftime("%Y-%m-%d") if order.custom_followup_at else "")
row.append(op.addon_to.positionid if op.addon_to_id else "")
acache = {}
for a in op.answers.all():
# We do not want to localize Date, Time and Datetime question answers, as those can lead
# to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French).
if a.question.type == Question.TYPE_CHOICE_MULTIPLE:
if a.question.type in (Question.TYPE_CHOICE_MULTIPLE, Question.TYPE_CHOICE):
acache[a.question_id] = set(o.pk for o in a.options.all())
elif a.question.type in Question.UNLOCALIZED_TYPES:
acache[a.question_id] = a.answer
@@ -722,6 +763,10 @@ class OrderListExporter(MultiSheetListExporter):
else:
for o in options[q.pk]:
row.append(_('Yes') if o.pk in acache.get(q.pk, set()) else _('No'))
elif q.type == Question.TYPE_CHOICE:
# Join is only necessary if the question type was modified but also keeps the code simpler here
# as we'd otherwise need some [0] and existance checks
row.append(", ".join(str(o.answer) for o in options[q.pk] if o.pk in acache.get(q.pk, set())))
else:
row.append(acache.get(q.pk, ''))
@@ -752,6 +797,7 @@ class OrderListExporter(MultiSheetListExporter):
_('Yes') if order.email_known_to_work else _('No'),
str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '',
]
row.append(op.checked_in_lists or "")
row.append(', '.join([
str(self.providers.get(p, p)) for p in sorted(set((op.payment_providers or '').split(',')))
if p and p != 'free'

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