mirror of
https://github.com/pretix/pretix.git
synced 2026-11-12 01:37:07 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8287ba4275 | ||
|
|
35ebfa0d47 | ||
|
|
8563d5bb38 | ||
|
|
12a00967c6 | ||
|
|
dc36c0e891 |
No files matched your search
@@ -56,7 +56,7 @@ calculated automatically.
|
||||
},
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
Cart positions
|
||||
==============
|
||||
|
||||
.. note::
|
||||
|
||||
This API is affected by an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Features or fields not yet available are marked with **NEW**.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
The API provides limited access to the cart position data model. This API currently only allows creating and deleting
|
||||
cart positions to reserve quota.
|
||||
|
||||
@@ -39,13 +31,12 @@ voucher integer Internal ID of
|
||||
addon_to integer Internal ID of the position this position is an add-on for (or ``null``)
|
||||
is_bundled boolean If ``addon_to`` is set, this shows whether this is a bundled product or an addon product
|
||||
subevent integer ID of the date inside an event series this position belongs to (or ``null``)
|
||||
answers list of objects Values of data fields (answers to user-defined questions)
|
||||
├ datafield string **NEW** The data field's ``identifier`` (internal reference)
|
||||
answers list of objects Answers to user-defined questions
|
||||
├ question integer Internal ID of the answered question
|
||||
├ answer string Text representation of the answer
|
||||
├ question_identifier string The question's ``identifier`` field
|
||||
├ options list of integers Internal IDs of selected option(s)s (only for choice types)
|
||||
├ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
├ question integer **Deprecated.** Internal ID of the data field
|
||||
└ question_identifier string **Read-only, deprecated.** The data field's ``identifier`` (internal reference)
|
||||
└ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
seat objects The assigned seat (or ``null``)
|
||||
├ id integer Internal ID of the seat instance
|
||||
├ name string Human-readable seat name
|
||||
@@ -208,8 +199,7 @@ Cart position endpoints
|
||||
* ``bundled`` (optional, expect a list of nested objects of cart positions)
|
||||
* ``answers``
|
||||
|
||||
* ``datafield`` **NEW**
|
||||
* ``question`` **DEPRECATED**
|
||||
* ``question``
|
||||
* ``answer``
|
||||
* ``options``
|
||||
|
||||
@@ -233,7 +223,7 @@ Cart position endpoints
|
||||
"attendee_email": null,
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
@@ -295,7 +285,7 @@ Cart position endpoints
|
||||
"attendee_email": null,
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
@@ -313,7 +303,7 @@ Cart position endpoints
|
||||
"attendee_email": null,
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
Check-in
|
||||
========
|
||||
|
||||
.. note::
|
||||
|
||||
This API is affected by an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Features or fields not yet available are marked with **NEW**.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
This page describes special APIs built for ticket scanning apps. For managing check-in configuration or other operations,
|
||||
please also see :ref:`rest-checkinlists`. The check-in list API also contains endpoints to obtain statistics or log
|
||||
failed scans.
|
||||
@@ -32,43 +24,41 @@ Checking a ticket in
|
||||
passed needs to be from a distinct event.
|
||||
|
||||
:query string expand: Expand a field inside the ``position`` object into a full object. Currently ``subevent``, ``item``, ``variation``, and ``answers.question`` are supported. Can be passed multiple times.
|
||||
:>json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
|
||||
:>json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
|
||||
:>json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
|
||||
:>json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
|
||||
:>json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
:>json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
|
||||
:<json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
|
||||
:<json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
|
||||
:<json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
|
||||
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
|
||||
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
|
||||
questions that have not been filled. This is usually used to upload offline scans that already happened,
|
||||
because there's no point in validating them since they happened whether they are valid or not. Defaults to ``false``.
|
||||
:>json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
|
||||
:<json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
|
||||
you do not implement question handling in your user interface, you **must**
|
||||
set this to ``false``. In that case, questions will just be ignored. Defaults
|
||||
to ``true``.
|
||||
:>json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
|
||||
:<json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
|
||||
Defaults to ``false`` and only works when ``include_pending`` is set on the check-in
|
||||
list.
|
||||
:>json object answers: If questions are supported/required, you may/must supply a mapping of ``identifier`` (`internal
|
||||
reference`) of data fields to their respective answers (**NEW**).
|
||||
For backwards compatibility, a mapping of data field ``id`` to answer is supported, as well.
|
||||
The answers should always be strings. In case of (multiple-)choice-type
|
||||
:<json object answers: If questions are supported/required, you may/must supply a mapping of question IDs to their
|
||||
respective answers. The answers should always be strings. In case of (multiple-)choice-type
|
||||
answers, the string should contain the (comma-separated) IDs of the selected options.
|
||||
:>json string nonce: You can set this parameter to a unique random value to identify this check-in. If you're sending
|
||||
:<json string nonce: You can set this parameter to a unique random value to identify this check-in. If you're sending
|
||||
this request twice with the same nonce, the second request will also succeed but will always
|
||||
create only one check-in object even when the previous request was successful as well. This
|
||||
allows for a certain level of idempotency and enables you to re-try after a connection failure.
|
||||
:>json string exchange_medium_type: To perform an exchange to a reusable medium, pass the type of the new reusable medium
|
||||
:>json string exchange_medium_identifier: To perform an exchange to a reusable media, pass the identifier of the new medium
|
||||
:>json boolean use_order_locale: Specifies that pretix should use the customer's language (``locale`` field from the
|
||||
:<json string exchange_medium_type: To perform an exchange to a reusable medium, pass the type of the new reusable medium
|
||||
:<json string exchange_medium_identifier: To perform an exchange to a reusable media, pass the identifier of the new medium
|
||||
:<json boolean use_order_locale: Specifies that pretix should use the customer's language (``locale`` field from the
|
||||
order) when building texts (currently only the ``reason_explanation`` response field).
|
||||
Defaults to ``false`` in which case the server will determine the language (currently
|
||||
the event default language, might change in the future with support for the
|
||||
``Accept-Language`` header).
|
||||
:>json boolean simulate: Do not actually perform the check-in, only simulate the response. The ``position`` response
|
||||
:<json boolean simulate: Do not actually perform the check-in, only simulate the response. The ``position`` response
|
||||
object will not reflect the simulated changes.
|
||||
:<json string status: ``"ok"``, ``"incomplete"``, ``"exchange"``, or ``"error"``
|
||||
:<json string reason: Reason code, only set on status ``"error"``, see below for possible values.
|
||||
:<json string reason_explanation: Human-readable explanation, only set on status ``"error"`` and reason ``"rules"``, can be null.
|
||||
:<json object position: Copy of the matching order position (if any was found). The contents are the same as the
|
||||
:>json string status: ``"ok"``, ``"incomplete"``, ``"exchange"``, or ``"error"``
|
||||
:>json string reason: Reason code, only set on status ``"error"``, see below for possible values.
|
||||
:>json string reason_explanation: Human-readable explanation, only set on status ``"error"`` and reason ``"rules"``, can be null.
|
||||
:>json object position: Copy of the matching order position (if any was found). The contents are the same as the
|
||||
:ref:`order-position-resource`, with the following differences: (1) The ``checkins`` value
|
||||
will only include check-ins for the selected list. (2) An additional boolean property
|
||||
``require_attention`` will inform you whether either the order or the item have the
|
||||
@@ -76,13 +66,13 @@ Checking a ticket in
|
||||
back to values from a parent product or from invoice addresses. (4) Additional properties
|
||||
``order__status``, ``order__valid_if_pending``, ``order__require_approval``, and
|
||||
``order__locale`` are included with details form the order for convenience.
|
||||
:<json boolean require_attention: Whether or not the ``require_attention`` flag is set on the item or order.
|
||||
:<json list checkin_texts: List of additional texts to show to the user.
|
||||
:<json object list: Excerpt of information about the matching :ref:`check-in list <rest-checkinlists>` (if any was found),
|
||||
:>json boolean require_attention: Whether or not the ``require_attention`` flag is set on the item or order.
|
||||
:>json list checkin_texts: List of additional texts to show to the user.
|
||||
:>json object list: Excerpt of information about the matching :ref:`check-in list <rest-checkinlists>` (if any was found),
|
||||
including the attributes ``id``, ``name``, ``event``, ``subevent``, and ``include_pending``.
|
||||
:<json object questions: List of questions to be answered for check-in, only set on status ``"incomplete"``.
|
||||
:<json object media_policy: Reusable media policy (see documentation on items), only set on status ``"exchange"``.
|
||||
:<json object media_type: Reusable media type (see documentation on items), only set on status ``"exchange"``.
|
||||
:>json object questions: List of questions to be answered for check-in, only set on status ``"incomplete"``.
|
||||
:>json object media_policy: Reusable media policy (see documentation on items), only set on status ``"exchange"``.
|
||||
:>json object media_type: Reusable media type (see documentation on items), only set on status ``"exchange"``.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -102,7 +92,7 @@ Checking a ticket in
|
||||
"datetime": null,
|
||||
"questions_supported": true,
|
||||
"answers": {
|
||||
"A1B2C3D4": "XS"
|
||||
"4": "XS"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +318,6 @@ Performing a ticket search
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
Check-in lists
|
||||
==============
|
||||
|
||||
.. note::
|
||||
|
||||
This API is affected by an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Features or fields not yet available are marked with **NEW**.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
@@ -577,7 +569,6 @@ Order position endpoints
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "A1B2C3D4",
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
@@ -618,29 +609,27 @@ Order position endpoints
|
||||
:query boolean untrusted_input: If set to true, the lookup parameter is **always** interpreted as a ``secret``, never
|
||||
as an ``id``. This should be always set if you are passing through untrusted, scanned
|
||||
data to avoid guessing of ticket IDs.
|
||||
:>json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
|
||||
:<json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
|
||||
you do not implement question handling in your user interface, you **must**
|
||||
set this to ``false``. In that case, questions will just be ignored. Defaults
|
||||
to ``true``.
|
||||
:>json boolean canceled_supported: When this parameter is set to ``true``, the response code ``canceled`` may be
|
||||
:<json boolean canceled_supported: When this parameter is set to ``true``, the response code ``canceled`` may be
|
||||
returned. Otherwise, canceled orders will return ``unpaid``. (**Deprecated**, in
|
||||
the future, this will be ignored and ``canceled`` may always be returned.)
|
||||
:>json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
:>json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
|
||||
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
|
||||
questions that have not been filled. This is usually used to upload offline scans that already happened,
|
||||
because there's no point in validating them since they happened whether they are valid or not. Defaults to ``false``.
|
||||
:>json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
|
||||
:>json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
|
||||
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
|
||||
:<json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
|
||||
Defaults to ``false`` and only works when ``include_pending`` is set on the check-in
|
||||
list.
|
||||
:>json string nonce: You can set this parameter to a unique random value to identify this check-in. If you're sending
|
||||
:<json string nonce: You can set this parameter to a unique random value to identify this check-in. If you're sending
|
||||
this request twice with the same nonce, the second request will also succeed but will always
|
||||
create only one check-in object even when the previous request was successful as well. This
|
||||
allows for a certain level of idempotency and enables you to re-try after a connection failure.
|
||||
:>json object answers: If questions are supported/required, you may/must supply a mapping of ``identifier`` (`internal
|
||||
reference`) of data fields to their respective answers (**NEW**).
|
||||
For backwards compatibility, a mapping of data field ``id`` to answer is supported, as well.
|
||||
The answers should always be strings. In case of (multiple-)choice-type
|
||||
:<json object answers: If questions are supported/required, you may/must supply a mapping of question IDs to their
|
||||
respective answers. The answers should always be strings. In case of (multiple-)choice-type
|
||||
answers, the string should contain the (comma-separated) IDs of the selected options.
|
||||
|
||||
**Example request**:
|
||||
@@ -659,7 +648,7 @@ Order position endpoints
|
||||
"questions_supported": true,
|
||||
"canceled_supported": true,
|
||||
"answers": {
|
||||
"A1B2C3D4": "XS"
|
||||
"4": "XS"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
|
||||
.. _rest-datafieldoptions:
|
||||
|
||||
Data field options
|
||||
================
|
||||
|
||||
.. note::
|
||||
|
||||
This API is part of an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Until the change, this resource is still available at ``/questions/(id)/options/``.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
:ref:`Data fields <rest-datafields>` of type "choice" or "multiple choice" can have different options attached.
|
||||
|
||||
As with data fields, data field options exist on two resource paths, depending on whether
|
||||
the data field is attached to orders or order positions. Therefore, each endpoint below has two
|
||||
different URLs.
|
||||
|
||||
The options resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the option
|
||||
position integer An integer, used for sorting
|
||||
identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
answer multi-lingual string The displayed value of this option
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(datafield)/options/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(datafield)/options/
|
||||
|
||||
Returns a list of all options for a given data field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/datafields/position/11/options/ 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": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only data fields with this value for the field ``active`` will be
|
||||
returned.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param datafield: The ``id`` field of the data field to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/data field does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(datafield)/options/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(datafield)/options/(id)/
|
||||
|
||||
Returns information on one option, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/datafields/position/1/options/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,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param datafield: The ``id`` field of the data field to fetch
|
||||
:param id: The ``id`` field of the option to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(datafield)/options/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(datafield)/options/
|
||||
|
||||
Create a new option
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/datafields/position/1/options/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/data field to create a option for
|
||||
:param event: The ``slug`` field of the event to create a option for
|
||||
:param datafield: The ``id`` field of the data field to create a option for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The option could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(datafield)/options/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(datafield)/options/(id)/
|
||||
|
||||
Update an option. 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 ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/datafields/position/1/options/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"position": 3
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
: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 data field to modify
|
||||
:param id: The ``id`` field of the option to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The option could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(datafield)/options/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(datafield)/options/(id)/
|
||||
|
||||
Delete an option.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/datafields/position/1/options/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 datafield: The ``id`` field of the data field to modify
|
||||
:param id: The ``id`` field of the option to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
@@ -1,428 +0,0 @@
|
||||
|
||||
.. _rest-datafields:
|
||||
|
||||
Data fields
|
||||
=========
|
||||
|
||||
.. note::
|
||||
|
||||
This API is part of an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Until the change, please keep using the endpoints at ``/questions/``.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Data fields define additional fields related to an order or an order position.
|
||||
By referencing data fields in a questionnaire, you can have customers or staff fill them out -- during or
|
||||
after checkout (web or POS), during check-in in the ticket scanner app, or in the backend.
|
||||
|
||||
There are two different resource paths for data fields, depending on whether the data field is attached
|
||||
to orders or order positions. Therefore, each endpoint below has two different URLs.
|
||||
|
||||
The data field resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the data field
|
||||
internal_name string **Required.** An internal field label
|
||||
identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
Must be unique per event, across all types of data fields.
|
||||
type string **Required.** The expected type of data. Valid options:
|
||||
|
||||
* ``N`` – number
|
||||
* ``S`` – one-line string
|
||||
* ``T`` – multi-line string
|
||||
* ``B`` – boolean
|
||||
* ``C`` – choice from a list
|
||||
* ``M`` – multiple choice from a list
|
||||
* ``F`` – file upload
|
||||
* ``D`` – date
|
||||
* ``H`` – time
|
||||
* ``W`` – date and time
|
||||
* ``CC`` – country code (ISO 3666-1 alpha-2)
|
||||
* ``TEL`` – telephone number
|
||||
show_during_checkin boolean If ``true``, the value of the data field will be shown
|
||||
during check-in (if the check-in client supports it).
|
||||
*Only supported on per-position data fields.*
|
||||
print_on_invoice boolean If ``true``, the data field will be shown on
|
||||
invoices.
|
||||
*Only supported on per-position data fields.*
|
||||
print_on_invoice_label multi-lingual string **Required if ``print_on_invoice`` is ``true``.** Label
|
||||
to print on the invoice before the value of this field.
|
||||
Otherwise `null`.
|
||||
options list of objects In case of data field type ``C`` or ``M``, this lists the
|
||||
available objects. Only writable during creation,
|
||||
use :ref:`separate endpoint <rest-datafieldoptions>` to modify this later.
|
||||
├ id integer Internal ID of the option
|
||||
├ position integer An integer, used for sorting
|
||||
├ identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
└ answer multi-lingual string The displayed value of this option
|
||||
valid_number_min string Minimum value for number fields (optional)
|
||||
valid_number_max string Maximum value for number fields (optional)
|
||||
valid_date_min date Minimum value for date fields (optional)
|
||||
valid_date_max date Maximum value for date fields (optional)
|
||||
valid_datetime_min datetime Minimum value for date and time fields (optional)
|
||||
valid_datetime_max datetime Maximum value for date and time fields (optional)
|
||||
valid_file_portrait boolean Turn on file validation for portrait photos
|
||||
valid_string_length_min integer Minimum length for string fields (optional)
|
||||
valid_string_length_max integer Maximum length for string fields (optional)
|
||||
referenced_by_questionnaires list of integers **Read-only.** List of questionnaire IDs that reference
|
||||
this data field
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/
|
||||
|
||||
Returns a list of all data fields within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/datafields/position/ 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,
|
||||
"internal_name": "T-Shirt size",
|
||||
"type": "C",
|
||||
"identifier": "WY3TP9SL",
|
||||
"show_during_checkin": false,
|
||||
"print_on_invoice": false,
|
||||
"print_on_invoice_label": null,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_string_length_min": null,
|
||||
"valid_string_length_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
],
|
||||
"referenced_by_questionnaires": [1]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:query string identifier: Only return questions with the given identifier string
|
||||
:query boolean ask_during_checkin: Only return questions that are or are not to be asked during check-in
|
||||
:query boolean required: Only return questions that are or are not required to fill in
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(id)/
|
||||
|
||||
Returns information on one data field, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/datafields/position/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,
|
||||
"internal_name": "T-Shirt size",
|
||||
"type": "C",
|
||||
"identifier": "WY3TP9SL",
|
||||
"show_during_checkin": false,
|
||||
"print_on_invoice": false,
|
||||
"print_on_invoice_label": null,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_string_length_min": null,
|
||||
"valid_string_length_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
],
|
||||
"referenced_by_questionnaires": [1]
|
||||
}
|
||||
|
||||
: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 question to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/
|
||||
|
||||
Create a new question
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/datafields/position/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"internal_name": "T-Shirt size",
|
||||
"type": "C",
|
||||
"show_during_checkin": false,
|
||||
"print_on_invoice": false,
|
||||
"print_on_invoice_label": null,
|
||||
"options": [
|
||||
{
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"internal_name": "T-Shirt size",
|
||||
"type": "C",
|
||||
"identifier": "WY3TP9SL",
|
||||
"show_during_checkin": false,
|
||||
"print_on_invoice": false,
|
||||
"print_on_invoice_label": null,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_string_length_min": null,
|
||||
"valid_string_length_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
],
|
||||
"referenced_by_questionnaires": [1]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||
:param event: The ``slug`` field of the event to create an item for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(id)/
|
||||
|
||||
Update a data field. 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 ``options`` field. If
|
||||
you need to update/delete options please use the nested dedicated endpoints.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/datafields/position/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"internal_name": "Clothing size"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"internal_name": "Clothing size",
|
||||
"type": "C",
|
||||
"identifier": "WY3TP9SL",
|
||||
"show_during_checkin": false,
|
||||
"print_on_invoice": false,
|
||||
"print_on_invoice_label": null,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_string_length_min": null,
|
||||
"valid_string_length_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
],
|
||||
"referenced_by_questionnaires": [1]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The question could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/datafields/position/(id)/
|
||||
/api/v1/organizers/(organizer)/events/(event)/datafields/order/(id)/
|
||||
|
||||
Delete a data field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/datafields/position/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 question to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ at :ref:`plugin-docs`.
|
||||
item_add-ons
|
||||
item_meta_properties
|
||||
item_program_times
|
||||
datafields
|
||||
datafield_options
|
||||
questionnaires
|
||||
questions
|
||||
question_options
|
||||
quotas
|
||||
|
||||
@@ -37,9 +37,12 @@ tax_rule integer The internal
|
||||
admission boolean ``true`` for items that grant admission to the event
|
||||
(such as primary tickets) and ``false`` for others
|
||||
(such as add-ons or merchandise).
|
||||
personalized boolean **DEPRECATED.** ``true`` for items that require personalization according
|
||||
personalized boolean ``true`` for items that require personalization according
|
||||
to event settings. Only affects system-level fields, not
|
||||
custom questions. Defaults to ``false``.
|
||||
custom questions. Currently only allowed for products with
|
||||
``admission`` set to ``true``. For backwards compatibility,
|
||||
when creating new items and this field is not given, it defaults
|
||||
to the same value as ``admission``.
|
||||
position integer An integer, used for sorting
|
||||
picture file A product picture to be displayed in the shop
|
||||
(can be ``null``).
|
||||
@@ -230,17 +233,6 @@ meta_data object Values set fo
|
||||
|
||||
The ``program_times`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2027.1
|
||||
|
||||
The ``personalized`` attribute has been deprecated.
|
||||
|
||||
For compatibility with existing applications:
|
||||
|
||||
* When retrieving products, `personalized` is `True` if any attached questionnaire asks for `attendee_name` and/or `attendee_email`.
|
||||
* When creating a new product, setting the `personalized` field to `True` will attach the "Attendee data" questionnaire to the new product. If no such questionnaire exists, it will be created.
|
||||
Before, the `personalized` field defaulted to the same value as `admission`. Now, it defaults to `false`.
|
||||
* When updating a product, the `personalized` field cannot be changed, returning an HTTP 400 error if attempted.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
Orders
|
||||
======
|
||||
|
||||
.. note::
|
||||
|
||||
This API is affected by an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Features or fields not yet available are marked with **NEW**.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
Order resource
|
||||
--------------
|
||||
|
||||
@@ -127,11 +119,6 @@ cancellation_date datetime Time of order c
|
||||
plugin_data object Additional data added by plugins.
|
||||
use_gift_cards list of strings List of unique gift card secrets that are used to pay
|
||||
for this order.
|
||||
answers list of objects **NEW** Values of data fields (answers to user-defined questions)
|
||||
├ datafield string The data field's ``identifier`` (internal reference)
|
||||
├ answer string Text representation of the answer
|
||||
├ options list of integers Internal IDs of selected option(s)s (only for choice types)
|
||||
└ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -175,10 +162,6 @@ answers list of objects **NEW** Values
|
||||
|
||||
The ``use_gift_cards`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2027.1
|
||||
|
||||
The ``answers`` attribute has been added.
|
||||
|
||||
.. _order-position-resource:
|
||||
|
||||
Order position resource
|
||||
@@ -248,13 +231,12 @@ print_logs list of objects List of print j
|
||||
downloads list of objects List of ticket download options
|
||||
├ output string Ticket output provider (e.g. ``pdf``, ``passbook``)
|
||||
└ url string Download URL
|
||||
answers list of objects Values of data fields (answers to user-defined questions)
|
||||
├ datafield string **NEW** The data field's ``identifier`` (internal reference)
|
||||
├ answer string Text representation of the answer
|
||||
answers list of objects Answers to user-defined questions
|
||||
├ question integer Internal ID of the answered question
|
||||
├ answer string Text representation of the answer (URL if answer is a file)
|
||||
├ question_identifier string The question's ``identifier`` field
|
||||
├ options list of integers Internal IDs of selected option(s)s (only for choice types)
|
||||
├ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
├ question integer **Deprecated.** Internal ID of the data field
|
||||
└ question_identifier string **Read-only, deprecated.** The data field's ``identifier`` (internal reference)
|
||||
└ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
seat objects The assigned seat. Can be ``null``.
|
||||
├ id integer Internal ID of the seat instance
|
||||
├ name string Human-readable seat name
|
||||
@@ -470,11 +452,10 @@ List of all orders
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "WY3TP9SL",
|
||||
"question": 12,
|
||||
"question_identifier": "WY3TP9SL",
|
||||
"answer": "Foo",
|
||||
"option_identifiers": [],
|
||||
"option_idenfiters": [],
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
@@ -507,15 +488,7 @@ List of all orders
|
||||
],
|
||||
"refunds": [],
|
||||
"cancellation_date": null,
|
||||
"plugin_data": {},
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "XYZ12345",
|
||||
"answer": "42",
|
||||
"option_identifiers": [],
|
||||
"options": []
|
||||
}
|
||||
]
|
||||
"plugin_data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -726,7 +699,6 @@ Fetching individual orders
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "WY3TP9SL",
|
||||
"question": 12,
|
||||
"question_identifier": "WY3TP9SL",
|
||||
"answer": "Foo",
|
||||
@@ -763,15 +735,7 @@ Fetching individual orders
|
||||
],
|
||||
"refunds": [],
|
||||
"cancellation_date": null,
|
||||
"plugin_data": {},
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "XYZ12345",
|
||||
"answer": "42",
|
||||
"option_identifiers": [],
|
||||
"options": []
|
||||
}
|
||||
]
|
||||
"plugin_data": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -1115,8 +1079,7 @@ Creating orders
|
||||
* ``discount`` (optional, only possible if ``price`` is set; attention: if this is set to not-``null`` on any position, automatic calculation of discounts will not run)
|
||||
* ``answers``
|
||||
|
||||
* ``datafield`` (**NEW**)
|
||||
* ``question`` (**DEPRECATED**)
|
||||
* ``question``
|
||||
* ``answer``
|
||||
* ``options``
|
||||
|
||||
@@ -1151,12 +1114,6 @@ Creating orders
|
||||
order isn't completely paid after its creation with ``use_gift_cards``, then a subsequent request to the payment
|
||||
endpoint is needed.
|
||||
|
||||
* **NEW** ``answers`` (optional). Values for order-level data fields.
|
||||
|
||||
* ``datafield``
|
||||
* ``answer``
|
||||
* ``options``
|
||||
|
||||
If you want to use add-on products, you need to set the ``positionid`` fields of all positions manually
|
||||
to incrementing integers starting with ``1``. Then, you can reference one of these
|
||||
IDs in the ``addon_to`` field of another position. Note that all add_ons for a specific position need to come
|
||||
@@ -1204,12 +1161,6 @@ Creating orders
|
||||
"internal_reference": "",
|
||||
"vat_id": ""
|
||||
},
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "XYZ12345",
|
||||
"answer": "42"
|
||||
}
|
||||
],
|
||||
"positions": [
|
||||
{
|
||||
"positionid": 1,
|
||||
@@ -1223,7 +1174,7 @@ Creating orders
|
||||
"addon_to": null,
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "WY3TP9SL",
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
@@ -1733,7 +1684,6 @@ List of all order positions
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "WY3TP9SL",
|
||||
"question": 12,
|
||||
"question_identifier": "WY3TP9SL",
|
||||
"answer": "Foo",
|
||||
@@ -1913,7 +1863,6 @@ Fetching individual positions
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"datafield": "WY3TP9SL",
|
||||
"question": 12,
|
||||
"question_identifier": "WY3TP9SL",
|
||||
"answer": "Foo",
|
||||
@@ -2022,7 +1971,7 @@ Manipulating individual positions
|
||||
|
||||
* ``answers``: If specified, you will need to provide **all** answers for this order position.
|
||||
Validation is handled the same way as when creating orders through the API. You are therefore
|
||||
expected to provide ``datafield``, ``answer``, and possibly ``options``. ``question`` is deprecated. ``question_identifier``
|
||||
expected to provide ``question``, ``answer``, and possibly ``options``. ``question_identifier``
|
||||
and ``option_identifiers`` will be ignored. As a special case, you can submit the magic value
|
||||
``"file:keep"`` as the answer to a file question to keep the current value without re-uploading it.
|
||||
|
||||
@@ -2118,7 +2067,7 @@ Manipulating individual positions
|
||||
* ``state``
|
||||
|
||||
* ``answers``: Validation is handled the same way as when creating orders through the API. You are therefore
|
||||
expected to provide ``datafield``, ``answer``, and possibly ``options``. ``question`` is deprecated. ``question_identifier``
|
||||
expected to provide ``question``, ``answer``, and possibly ``options``. ``question_identifier``
|
||||
and ``option_identifiers`` will be ignored. As a special case, you can submit the magic value
|
||||
``"file:keep"`` as the answer to a file question to keep the current value without re-uploading it.
|
||||
|
||||
|
||||
@@ -1,7 +1,229 @@
|
||||
Question options
|
||||
================
|
||||
|
||||
.. warning:: This resource is **deprecated**.
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
New applications must use the :ref:`rest-datafieldoptions` resource.
|
||||
Questions of type "choice" or "multiple choice" can have different options attached.
|
||||
The options resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the option
|
||||
position integer An integer, used for sorting
|
||||
identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
answer multi-lingual string The displayed value of this option
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/
|
||||
|
||||
Returns a list of all options for a given question.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/11/options/ 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": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only questions with this value for the field ``active`` will be
|
||||
returned.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param question: The ``id`` field of the question to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/question does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/(id)/
|
||||
|
||||
Returns information on one option, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/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,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param question: The ``id`` field of the question to fetch
|
||||
:param id: The ``id`` field of the option to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/
|
||||
|
||||
Creates a new option
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/question to create a option for
|
||||
:param event: The ``slug`` field of the event to create a option for
|
||||
:param question: The ``id`` field of the question to create a option for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The option could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/(id)/
|
||||
|
||||
Update an option. 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 ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"position": 3
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:param id: The ``id`` field of the option to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The option could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/options/(id)/
|
||||
|
||||
Delete an option.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/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 question to modify
|
||||
:param id: The ``id`` field of the option to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
@@ -1,379 +0,0 @@
|
||||
|
||||
.. _rest-questionnaires:
|
||||
|
||||
Questionnaires
|
||||
=========
|
||||
|
||||
.. note::
|
||||
|
||||
This API is part of an upcoming larger change to our API. The API documentation already reflects the future
|
||||
version. Until the change, please keep using the endpoints at ``/questions/``.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
Questionnaires are attached to one or more products, and a product can have multiple questionnaires.
|
||||
They consist of questionnaire rows, each of which can be one of the following:
|
||||
|
||||
Reference to system field
|
||||
To reference a system field, use one of the identifier strings from the table below in the row's `datafield` attribute.
|
||||
Currently, system fields are only defined on order positions, not on orders.
|
||||
|
||||
=============== =========================== ============================
|
||||
Container Identifier Label
|
||||
=============== =========================== ============================
|
||||
Order position `"@attendee_name_parts"` Attendee name
|
||||
Order position `"@attendee_email"` Attendee email
|
||||
Order position `"@company"` Company
|
||||
Order position `"@street"` Street
|
||||
Order position `"@zipcode"` ZIP code
|
||||
Order position `"@city"` City
|
||||
Order position `"@state"` State
|
||||
Order position `"@country"` Country
|
||||
=============== =========================== ============================
|
||||
|
||||
|
||||
Reference to user-defined data field
|
||||
To reference a :ref:`user-defined data field <rest-datafields>`, use its internal reference (`identifier`)
|
||||
in the row's `datafield` attribute.
|
||||
|
||||
|
||||
Static explanation text / subheading
|
||||
To add a static text block, set the row's `datafield` attribute to `null`. In this case, the text
|
||||
from the `label` attribute is displayed as a subheading, and the `help_text` attribute as a normal paragraph.
|
||||
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the questionnaire
|
||||
type string The type of questionnaire. Valid options:
|
||||
|
||||
* ``order_purchase`` — Order-wide, before purchase
|
||||
* ``position_purchase`` — Per product, before purchase
|
||||
* ``position_attendee`` — Per product, via attendee link
|
||||
* ``position_checkin`` — Per product, at check-in
|
||||
* ``position_hidden`` — Per product, hidden
|
||||
internal_name string Internal label for the questionnaire.
|
||||
items list of integers List of item IDs this questionnaire is assigned to.
|
||||
*Only supported on per-product questionnaires.*
|
||||
position integer An integer, used for sorting
|
||||
all_sales_channels boolean If ``true`` (default), the questions from this questionnaire
|
||||
are asked on all sales channels.
|
||||
limit_sales_channels list of strings List of sales channel identifiers the questions are asked on
|
||||
if ``all_sales_channels`` is ``false``.
|
||||
rows list of objects List of all questionnaire rows.
|
||||
├ datafield string Reference to a data field (see above)
|
||||
├ required boolean If ``true``, the question needs to be filled out.
|
||||
├ label multi-lingual string The field label shown to the customer. In case of a static
|
||||
text block, the subheading.
|
||||
├ help_text multi-lingual string The help text shown to the customer.
|
||||
├ dependency_datafield string ``datafield`` reference of a different row in the same
|
||||
questionnaire.
|
||||
The current question will only be shown if the question
|
||||
given in this attribute is set to one of the values given
|
||||
in ``dependency_values``.
|
||||
├ dependency_values list of strings If ``dependency_datafield`` is set to reference a boolean
|
||||
data field, this should be ``["True"]`` or ``["False"]``.
|
||||
Otherwise, it should be a list of ``identifier`` values
|
||||
of question options.
|
||||
├ rendered_help_text string **Read-only.** Markdown contents from help_text rendered
|
||||
to HTML
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questionnaires/
|
||||
|
||||
Returns a list of all questionnaires within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questionnaires/ 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": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "position_purchase",
|
||||
"internal_name": "Attendee data",
|
||||
"items": [1, 2],
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "@attendee_name_parts",
|
||||
"required": false,
|
||||
"label": {"en": "Attendee name"},
|
||||
"help_text": {},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": ""
|
||||
},
|
||||
{
|
||||
"datafield": "@attendee_email",
|
||||
"required": false,
|
||||
"label": {"en": "Attendee email"},
|
||||
"help_text": {"en": "*We'll send you our program guide a few days before the event.*"},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": "<em>We'll send you our program guide a few days before the event.</em>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "order_purchase",
|
||||
"internal_name": "Per-order questions",
|
||||
"items": [],
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "87Y8DCS9",
|
||||
"required": false,
|
||||
"label": {"en": "How did you find us?"},
|
||||
"help_text": {},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:query string type: Only return questionnaires with the given type
|
||||
:query string items: Only return questionnaires associated with the given item (internal item ID)
|
||||
:query boolean sales_channel: Only return questionnaires visible on the given sales channel (sales channel identifier string)
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questionnaires/(id)/
|
||||
|
||||
Returns information on one questionnaire, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questionnaires/2/ 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": 2,
|
||||
"type": "order_purchase",
|
||||
"internal_name": "Per-order questions",
|
||||
"items": [],
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "87Y8DCS9",
|
||||
"required": false,
|
||||
"label": {"en": "How did you find us?"},
|
||||
"help_text": {},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
: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 questionnaire to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/questionnaires/
|
||||
|
||||
Create a new questionnaire
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/questionnaires/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"type": "order_purchase",
|
||||
"internal_name": "Per-order questions",
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "87Y8DCS9",
|
||||
"required": false,
|
||||
"label": {"en": "How did you find us?"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"type": "order_purchase",
|
||||
"internal_name": "Per-order questions",
|
||||
"items": [],
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "87Y8DCS9",
|
||||
"required": false,
|
||||
"label": {"en": "How did you find us?"},
|
||||
"help_text": {},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create a questionnaire for
|
||||
:param event: The ``slug`` field of the event to create a questionnaire for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The questionnaire could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/questionnaires/(id)/
|
||||
|
||||
Update a questionnaire. 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 only change all ``rows`` en bloc, or keep all of them unchanged in case of a ``PATCH``. If you
|
||||
change ``rows``, you need to specify all fields of the resource.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/questionnaires/2/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"internal_name": "Questions asked per order"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"type": "order_purchase",
|
||||
"internal_name": "Questions asked per order",
|
||||
"items": [],
|
||||
"position": 0,
|
||||
"all_sales_channels": true,
|
||||
"limit_sales_channels": [],
|
||||
"rows": [
|
||||
{
|
||||
"datafield": "87Y8DCS9",
|
||||
"required": false,
|
||||
"label": {"en": "How did you find us?"},
|
||||
"help_text": {},
|
||||
"dependency_datafield": null,
|
||||
"dependency_values": [],
|
||||
"rendered_help_text": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the questionnaire to modify
|
||||
:param event: The ``slug`` field of the event of the questionnaire to modify
|
||||
:param id: The ``id`` field of the questionnaire to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The questionnaire could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/questionnaires/(id)/
|
||||
|
||||
Delete a questionnaire.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/questionnaires/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 of the questionnaire to modify
|
||||
:param event: The ``slug`` field of the event of the questionnaire to modify
|
||||
:param id: The ``id`` field of the questionnaire to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
@@ -8,23 +8,10 @@
|
||||
Questions
|
||||
=========
|
||||
|
||||
.. warning:: This resource is **deprecated**. It is only provided for compatibility with existing applications
|
||||
and should not be used in new development.
|
||||
|
||||
New applications must use the :ref:`rest-datafields` and :ref:`rest-questionnaires` resources.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted pretix with
|
||||
version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
|
||||
This resource will continue to work in read-only mode on events where the
|
||||
:ref:`questionnaire configuration <rest-questionnaires>` is compatible with the old data model.
|
||||
If incompatible configuration is detected, all endpoints return HTTP 410.
|
||||
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Questions define additional fields related to an order position that need to be filled out by customers during checkout.
|
||||
Questions define additional fields that need to be filled out by customers during checkout.
|
||||
The question resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
@@ -97,10 +84,6 @@ dependency_value string An old version
|
||||
|
||||
The ``show_during_checkin`` attribute has been added.
|
||||
|
||||
.. versionchanged:: 2026.[TODO]
|
||||
|
||||
The questions resource was deprecated and replaced by the :ref:`rest-datafields` and :ref:`rest-questionnaires` resources.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -266,13 +249,6 @@ Endpoints
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/questions/
|
||||
|
||||
.. warning:: This endpoint is **deprecated** and will be removed as part of an upcoming API change.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted
|
||||
pretix with version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
After the change, instead create a :ref:`data field <rest-datafields>` first, then add
|
||||
it to a :ref:`questionnaire <rest-questionnaires>`.
|
||||
|
||||
Creates a new question
|
||||
|
||||
**Example request**:
|
||||
@@ -375,13 +351,6 @@ Endpoints
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
.. warning:: This endpoint is **deprecated** and will be removed as part of an upcoming API change.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted
|
||||
pretix with version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
After the change, instead update the relevant :ref:`data field <rest-datafields>`, or
|
||||
the reference to it inside a :ref:`questionnaire <rest-questionnaires>`.
|
||||
|
||||
Update a question. 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.
|
||||
@@ -468,14 +437,6 @@ Endpoints
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
|
||||
.. warning:: This endpoint is **deprecated** and will be removed as part of an upcoming API change.
|
||||
The new version is expected to be released for hosted pretix early December and for self-hosted
|
||||
pretix with version 2027.1.
|
||||
You can find more information `on our blog <https://pretix.eu/about/en/blog/20261110-questionnaires/>`_.
|
||||
After the change, insteadremove the questionnaire child from its :ref:`questionnaire <rest-questionnaires>`,
|
||||
or delete the relevant :ref:`data field <rest-datafields>`.
|
||||
|
||||
Delete a question.
|
||||
|
||||
**Example request**:
|
||||
|
||||
+6
-5
@@ -27,7 +27,7 @@ classifiers = [
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"arabic-reshaper==3.1.0", # Support for Arabic in reportlab
|
||||
"arabic-reshaper==3.0.1", # Support for Arabic in reportlab
|
||||
"babel",
|
||||
"BeautifulSoup4==4.15.*",
|
||||
"bleach==6.4.*",
|
||||
@@ -60,6 +60,7 @@ dependencies = [
|
||||
"djangorestframework>=3.18.3",
|
||||
"drf_ujson2==1.7.*",
|
||||
"geoip2==5.*",
|
||||
"importlib_metadata==9.*", # Polyfill, we can probably drop this once we require Python 3.10+
|
||||
"isoweek",
|
||||
"jsonschema",
|
||||
"kombu==5.6.*",
|
||||
@@ -83,7 +84,7 @@ dependencies = [
|
||||
"pycryptodome==3.24.*",
|
||||
"pypdf==6.20.*",
|
||||
"python-bidi==0.6.*", # Support for Arabic in reportlab
|
||||
"python-dateutil==4.0.*",
|
||||
"python-dateutil==3.0.*",
|
||||
"pytz",
|
||||
"pytz-deprecation-shim==0.1.*",
|
||||
"pyuca",
|
||||
@@ -109,13 +110,13 @@ dev = [
|
||||
"aiohttp==3.14.*",
|
||||
"coverage",
|
||||
"coveralls",
|
||||
"fakeredis==2.40.*",
|
||||
"flake8==7.5.*",
|
||||
"fakeredis==2.39.*",
|
||||
"flake8==7.4.*",
|
||||
"freezegun",
|
||||
"isort==9.0.*",
|
||||
"pep8-naming==0.15.*",
|
||||
"potypo",
|
||||
"pytest-asyncio>=1.4.1.post1",
|
||||
"pytest-asyncio>=1.4.0",
|
||||
"pytest-cache",
|
||||
"pytest-cov",
|
||||
"pytest-django==4.*",
|
||||
|
||||
@@ -117,7 +117,6 @@ class TransmissionInfoSerializer(serializers.Serializer):
|
||||
super().__init__(*args, **kwargs)
|
||||
for k, v in transmission_type.invoice_address_form_fields.items():
|
||||
self.fields[k] = form_field_to_serializer_field(v)
|
||||
self.fields[k].required = False # invoice_address_form_fields_required is checked by parent serializer
|
||||
|
||||
|
||||
class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
||||
|
||||
@@ -29,7 +29,6 @@ from typing import List, Optional, Protocol
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import DatabaseError, transaction
|
||||
from django.utils.functional import classproperty
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
@@ -102,8 +101,9 @@ class OutboundSyncProvider:
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.close()
|
||||
|
||||
@classproperty
|
||||
def display_name(cls): # noqa: N805
|
||||
@classmethod
|
||||
@property
|
||||
def display_name(cls):
|
||||
return str(cls.identifier)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -83,8 +83,6 @@ from .organizer import Organizer, Team
|
||||
if TYPE_CHECKING:
|
||||
from hierarkey.proxy import HierarkeyProxy
|
||||
|
||||
from .organizer import SalesChannel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -338,18 +336,12 @@ class EventMixin:
|
||||
return safe_string(json.dumps(eventdict))
|
||||
|
||||
@classmethod
|
||||
def annotated(cls, qs, channel: "str | SalesChannel | list[SalesChannel]", voucher=None):
|
||||
def annotated(cls, qs, channel, voucher=None):
|
||||
# Channel can currently be a SalesChannel or a str, since we need that compatibility, but a SalesChannel
|
||||
# makes the query SIGNIFICANTLY faster
|
||||
from pretix.base.models import Item, ItemVariation, Quota, SalesChannel
|
||||
|
||||
assert isinstance(channel, (SalesChannel, str, list))
|
||||
|
||||
if isinstance(channel, SalesChannel):
|
||||
channel = [channel]
|
||||
|
||||
if isinstance(channel, list):
|
||||
assert all(isinstance(c, SalesChannel) for c in channel)
|
||||
assert isinstance(channel, (SalesChannel, str))
|
||||
|
||||
sq_active_item = Item.objects.using(settings.DATABASE_REPLICA).filter_available(channel=channel, voucher=voucher).filter(
|
||||
Q(variations__isnull=True)
|
||||
@@ -372,8 +364,8 @@ class EventMixin:
|
||||
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
|
||||
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__identifier=channel))
|
||||
else:
|
||||
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__in=channel))
|
||||
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__in=channel))
|
||||
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels=channel))
|
||||
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels=channel))
|
||||
|
||||
if voucher:
|
||||
if voucher.variation_id:
|
||||
@@ -1669,17 +1661,11 @@ class SubEvent(EventMixin, LoggedModel):
|
||||
return qs_annotated
|
||||
|
||||
@classmethod
|
||||
def annotated(cls, qs, channel: "str | SalesChannel | list[SalesChannel]", voucher=None):
|
||||
def annotated(cls, qs, channel, voucher=None):
|
||||
from .items import SubEventItem, SubEventItemVariation
|
||||
from .organizer import SalesChannel
|
||||
|
||||
assert isinstance(channel, (SalesChannel, str, list))
|
||||
|
||||
if isinstance(channel, SalesChannel):
|
||||
channel = [channel]
|
||||
|
||||
if isinstance(channel, list):
|
||||
assert all(isinstance(c, SalesChannel) for c in channel)
|
||||
assert isinstance(channel, (str, SalesChannel))
|
||||
|
||||
qs = super().annotated(qs, channel, voucher=voucher)
|
||||
qs = qs.annotate(
|
||||
|
||||
@@ -313,14 +313,7 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False, allow_
|
||||
# makes the query SIGNIFICANTLY faster
|
||||
from .organizer import SalesChannel
|
||||
|
||||
assert isinstance(channel, (SalesChannel, str, list))
|
||||
|
||||
if isinstance(channel, SalesChannel):
|
||||
channel = [channel]
|
||||
|
||||
if isinstance(channel, list):
|
||||
assert all(isinstance(c, SalesChannel) for c in channel)
|
||||
|
||||
assert isinstance(channel, (SalesChannel, str))
|
||||
q = (
|
||||
# IMPORTANT: If this is updated, also update the ItemVariation query
|
||||
# in models/event.py: EventMixin.annotated()
|
||||
@@ -332,7 +325,7 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False, allow_
|
||||
if isinstance(channel, str):
|
||||
q &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
|
||||
else:
|
||||
q &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__in=channel))
|
||||
q &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels=channel))
|
||||
|
||||
if not allow_addons:
|
||||
q &= Q(Q(category__isnull=True) | Q(category__is_addon=False))
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
import os
|
||||
import sys
|
||||
from enum import Enum
|
||||
from importlib import metadata
|
||||
from typing import List
|
||||
|
||||
import importlib_metadata as metadata
|
||||
from django.apps import AppConfig, apps
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
@@ -2176,8 +2176,7 @@ class OrderChangeManager:
|
||||
subevent=a.subevent,
|
||||
voucher=None,
|
||||
base_qs=Item.objects.filter(pk=a.item.pk),
|
||||
allow_addons=True,
|
||||
ignore_hide_sold_out_for_item_ids={a.item.pk}
|
||||
allow_addons=True
|
||||
)
|
||||
if (not items) or items[0].current_unavailability_reason:
|
||||
return False
|
||||
|
||||
@@ -126,10 +126,10 @@ def generate_seats(event, subevent, plan, mapping, blocked_guids=None):
|
||||
for s in current_seats.values():
|
||||
if s.has_op:
|
||||
raise SeatProtected(_('You can not change the plan since seat "%s" is not present in the new plan and is '
|
||||
'already sold.'), s.name)
|
||||
'already sold.', s.name))
|
||||
if s.has_v:
|
||||
raise SeatProtected(_('You can not change the plan since seat "%s" is not present in the new plan and is '
|
||||
'already used in a voucher.'), s.name)
|
||||
'already used in a voucher.', s.name))
|
||||
|
||||
Seat.objects.bulk_create(create_seats)
|
||||
CartPosition.objects.filter(addon_to__seat__in=[s.pk for s in current_seats.values()]).delete()
|
||||
|
||||
@@ -23,10 +23,10 @@ import json
|
||||
import logging
|
||||
import pathlib
|
||||
import re
|
||||
from importlib import metadata
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import urlopen
|
||||
|
||||
import importlib_metadata as metadata
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<link rel="stylesheet" type="text/x-scss" href="{% static "pretixcontrol/scss/main.scss" %}" />
|
||||
<link rel="stylesheet" type="text/x-scss" href="{% static "lightbox/css/lightbox.scss" %}" />
|
||||
{% endcompress %}
|
||||
{% vite_importmap %}
|
||||
{% if DEBUG %}
|
||||
<script type="text/javascript" src="{% url 'javascript-catalog' lang=request.LANGUAGE_CODE %}"></script>
|
||||
{% else %}
|
||||
@@ -88,6 +87,7 @@
|
||||
<meta name="theme-color" content="#3b1c4a">
|
||||
<meta name="referrer" content="origin">
|
||||
|
||||
{% vite_importmap %}
|
||||
{% block custom_header %}{% endblock %}
|
||||
</head>
|
||||
<body data-datetimeformat="{{ js_datetime_format }}" data-timeformat="{{ js_time_format }}"
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
from importlib import metadata as metadata
|
||||
|
||||
import importlib_metadata as metadata
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
|
||||
@@ -196,14 +196,6 @@ OPTIONS = OrderedDict([
|
||||
'offsets': [46 * mm, 46 * mm],
|
||||
'pagesize': pagesizes.A4,
|
||||
}),
|
||||
('herma_75x40', {
|
||||
'name': 'HERMA 75 x 40 mm (9010)',
|
||||
'cols': 2,
|
||||
'rows': 6,
|
||||
'margins': [28.5 * mm, 25 * mm, 28.5 * mm, 25 * mm],
|
||||
'offsets': [85 * mm, 40 * mm],
|
||||
'pagesize': pagesizes.A4,
|
||||
}),
|
||||
('herma_88.9x33.87', {
|
||||
'name': 'HERMA 88,9 x 33,87 mm (4515)',
|
||||
'cols': 2,
|
||||
|
||||
@@ -219,11 +219,6 @@ TEMPLATES = {
|
||||
"pagesize": (75 * mm, 52 * mm),
|
||||
"layout": _simple_template(75 * mm, 52 * mm),
|
||||
},
|
||||
"75x40": {
|
||||
"label": format_lazy(_("{width} x {height} mm label"), width=75, height=40),
|
||||
"pagesize": (75 * mm, 40 * mm),
|
||||
"layout": _simple_template(75 * mm, 40 * mm),
|
||||
},
|
||||
"70x36": {
|
||||
"label": format_lazy(_("{width} x {height} mm label"), width=70, height=36),
|
||||
"pagesize": (70 * mm, 36 * mm),
|
||||
|
||||
@@ -98,32 +98,19 @@ class TicketLayoutSerializer(I18nAwareModelSerializer):
|
||||
return d
|
||||
|
||||
def validate(self, attrs):
|
||||
if attrs.get('default') and self.context['event'].ticket_layouts.filter(default=True).exists():
|
||||
if attrs.get('default') and self.context['event'].ticket_layouts.filter(default=True).exists:
|
||||
raise ValidationError('You cannot have two layouts with default = True')
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data["event"] = self.context["event"]
|
||||
background = validated_data.pop("background", None)
|
||||
instance = super().create(validated_data)
|
||||
if background:
|
||||
instance.background.save('background.pdf', background)
|
||||
return instance
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
background = validated_data.pop("background", None)
|
||||
if background:
|
||||
if instance.background and TicketLayout.objects.filter(background=instance.background).count() == 1:
|
||||
instance.background.delete()
|
||||
instance.background.save('background.pdf', background)
|
||||
return super().update(instance, validated_data)
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class TicketLayoutViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = TicketLayoutSerializer
|
||||
queryset = TicketLayout.objects.none()
|
||||
lookup_field = 'id'
|
||||
write_permission = 'event.settings.general:write'
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.event.ticket_layouts.all()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
{% for provider in request.organizer.sso_providers.all %}
|
||||
{% if provider.is_active %}
|
||||
<a href="{% abseventurl request.organizer "presale:organizer.customer.login" provider=provider.pk %}?next={% if request.domain_mode == 'event' or request.domain_mode == 'organizer_alternative' %}{{ request.scheme }}://{{ request.get_host }}{% endif %}{{ request.get_full_path|urlencode }}"
|
||||
<a href="{% eventurl request.organizer "presale:organizer.customer.login" provider=provider.pk %}?next={% if request.domain_mode == 'event' or request.domain_mode == 'organizer_alternative' %}{{ request.scheme }}://{{ request.get_host }}{% endif %}{{ request.get_full_path|urlencode }}"
|
||||
class="btn btn-primary btn-lg btn-block" data-open-in-popup-window>
|
||||
{{ provider.button_label }}
|
||||
</a>
|
||||
|
||||
@@ -76,7 +76,7 @@ from pretix.base.models.tax import TaxedPrice
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.services.invoices import (
|
||||
generate_cancellation, generate_invoice, invoice_pdf, invoice_pdf_task,
|
||||
invoice_qualified, transmit_invoice,
|
||||
invoice_qualified,
|
||||
)
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, _try_auto_refund, cancel_order,
|
||||
@@ -907,9 +907,6 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
|
||||
self.order.log_action('pretix.event.order.invoice.reissued', data={
|
||||
'invoice': inv.pk
|
||||
})
|
||||
transmit_invoice.apply_async(args=(c.event_id, c.pk, True))
|
||||
if c.pk != inv.pk:
|
||||
transmit_invoice.apply_async(args=(inv.event_id, inv.pk, True))
|
||||
messages.success(self.request, _('The invoice has been reissued.'))
|
||||
except Exception as e:
|
||||
self.order.log_action("pretix.event.order.invoice.failed", data={
|
||||
|
||||
@@ -35,7 +35,6 @@ import calendar
|
||||
import hashlib
|
||||
import math
|
||||
import operator
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from functools import reduce
|
||||
@@ -382,11 +381,7 @@ class EventListMixin:
|
||||
def _set_week_year(self):
|
||||
if 'date' in self.request.GET:
|
||||
try:
|
||||
input = self.request.GET.get('date')
|
||||
# Our parameters for the single-digit weeks of the year are 2027-W2, as emitted by Django's "W" format code,
|
||||
# but dateutil 4.0 is strict about ISO and only accepts 2027-W02 as valid.
|
||||
input = re.sub('-W([0-9])$', '-W0\\1', input)
|
||||
iso = dateutil.parser.isoparse(input).isocalendar()
|
||||
iso = dateutil.parser.isoparse(self.request.GET.get('date')).isocalendar()
|
||||
except ValueError:
|
||||
iso = time_machine_now().isocalendar()
|
||||
self.year = iso[0]
|
||||
|
||||
@@ -41,7 +41,7 @@ from json import loads
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from importlib import metadata
|
||||
import importlib_metadata as metadata
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.crypto import get_random_string
|
||||
from kombu import Queue
|
||||
|
||||
@@ -25,10 +25,8 @@ import tempfile
|
||||
|
||||
tmpdir = tempfile.TemporaryDirectory()
|
||||
os.environ.setdefault('DATA_DIR', tmpdir.name)
|
||||
if os.path.exists('tests/ci_sqlite.cfg'):
|
||||
os.environ.setdefault('PRETIX_CONFIG_FILE', 'tests/ci_sqlite.cfg')
|
||||
else:
|
||||
os.environ.setdefault("PRETIX_CONFIG_FILE", "")
|
||||
if os.path.exists('test/sqlite.cfg'):
|
||||
os.environ.setdefault('PRETIX_CONFIG_FILE', 'test/sqlite.cfg')
|
||||
|
||||
from pretix.settings import * # NOQA
|
||||
|
||||
@@ -102,4 +100,3 @@ class DisableMigrations(object):
|
||||
|
||||
if not os.environ.get("GITHUB_WORKFLOW", ""):
|
||||
MIGRATION_MODULES = DisableMigrations()
|
||||
VITE_DEV_MODE = True
|
||||
@@ -147,7 +147,6 @@ def test_api_create(env, token_client):
|
||||
assert resp.status_code == 201
|
||||
tl = env[0].ticket_layouts.get(pk=resp.data["id"])
|
||||
assert tl.background
|
||||
assert "cachedfile" not in tl.background.name
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -164,21 +163,6 @@ def test_api_create_validate_default(env, token_client):
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"non_field_errors": ["You cannot have two layouts with default = True"]}
|
||||
|
||||
env[0].ticket_layouts.filter(default=True).update(default=False)
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/ticketlayouts/'.format(env[0].slug, env[0].slug),
|
||||
{
|
||||
'name': 'Foo',
|
||||
'default': True,
|
||||
'layout': [],
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
tl = env[0].ticket_layouts.get(pk=resp.data["id"])
|
||||
assert tl.default
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_api_create_validate_layout(env, token_client):
|
||||
@@ -231,7 +215,6 @@ def test_api_update(env, token_client):
|
||||
assert json.loads(env[1].layout) == [
|
||||
{"type": "barcodearea", "left": "7.00", "bottom": "11.15", "size": "45.00", "content": "secret"}
|
||||
]
|
||||
assert "cachedfile" not in env[1].background.name
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -247,18 +230,6 @@ def test_api_update_validate_default(env, token_client):
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"non_field_errors": ["You cannot have two layouts with default = True"]}
|
||||
|
||||
env[0].ticket_layouts.filter(default=True).update(default=False)
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/ticketlayouts/{}/'.format(env[0].slug, env[0].slug, tl2.pk),
|
||||
{
|
||||
"default": True,
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
tl2.refresh_from_db()
|
||||
assert tl2.default
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_api_delete(env, token_client):
|
||||
@@ -356,22 +327,3 @@ def test_renderer_batch_invalid(env, token_client, position):
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"parts": ["Please do not submit more than 1000 parts."]}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_api_permission(env, token_client):
|
||||
t = env[0].organizer.teams.get()
|
||||
t.limit_event_permissions = {"event.orders:read": True}
|
||||
t.all_event_permissions = False
|
||||
t.save()
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/ticketlayouts/{}/'.format(env[0].slug, env[0].slug, env[1].pk),
|
||||
{
|
||||
"name": "Bar",
|
||||
"layout": [
|
||||
{"type": "barcodearea", "left": "7.00", "bottom": "11.15", "size": "45.00", "content": "secret"}
|
||||
]
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
@@ -1393,61 +1393,6 @@ class OrderChangeAddonsTest(BaseOrdersTest):
|
||||
assert a.item == self.workshop2
|
||||
assert a.variation == self.workshop2a
|
||||
|
||||
def test_quota_sold_out_change_hide_sold_out(self):
|
||||
self.event.settings.hide_sold_out = True
|
||||
self.workshopquota.size = 1
|
||||
self.workshopquota.items.remove(self.workshop2)
|
||||
self.workshopquota.variations.remove(self.workshop2a)
|
||||
self.workshopquota.variations.remove(self.workshop2b)
|
||||
self.workshopquota.save()
|
||||
self.workshopquota2 = Quota.objects.create(event=self.event, name='Workshop 2', size=5)
|
||||
self.workshopquota2.items.add(self.workshop2)
|
||||
self.workshopquota2.variations.add(self.workshop2a)
|
||||
self.workshopquota2.variations.add(self.workshop2b)
|
||||
|
||||
with scopes_disabled():
|
||||
OrderPosition.objects.create(
|
||||
order=self.order,
|
||||
item=self.workshop1,
|
||||
variation=None,
|
||||
price=Decimal("12"),
|
||||
addon_to=self.ticket_pos,
|
||||
attendee_name_parts={'full_name': "Peter"}
|
||||
)
|
||||
self.order.total += Decimal("12")
|
||||
self.order.save()
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert 'Workshop 1' in response.content.decode()
|
||||
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert doc.select(f'input[name=cp_{self.ticket_pos.pk}_item_{self.workshop1.pk}]')[0].attrs['checked']
|
||||
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret),
|
||||
{
|
||||
f'cp_{self.ticket_pos.pk}_variation_{self.workshop2.pk}_{self.workshop2a.pk}': '1'
|
||||
},
|
||||
follow=True
|
||||
)
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert 'alert-danger' not in response.content.decode()
|
||||
|
||||
form_data = extract_form_fields(doc.select('.main-box form')[0])
|
||||
form_data['confirm'] = 'true'
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), form_data, follow=True
|
||||
)
|
||||
assert 'alert-success' in response.content.decode()
|
||||
|
||||
with scopes_disabled():
|
||||
a = self.ticket_pos.addons.get(canceled=False)
|
||||
assert a.item == self.workshop2
|
||||
assert a.variation == self.workshop2a
|
||||
|
||||
def _assert_ws2a_not_allowed(self):
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
|
||||
@@ -422,42 +422,37 @@ class OrdersTest(BaseOrdersTest):
|
||||
with scopes_disabled():
|
||||
assert self.order.invoices.count() == 1
|
||||
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/modify' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), {
|
||||
'%s-question_%s' % (self.ticket_pos.id, self.question.id): 'ABC',
|
||||
'zipcode': '12345',
|
||||
'street': 'Main Street',
|
||||
'city': 'Heidelberg',
|
||||
'country': 'DE',
|
||||
'transmission_type': 'email',
|
||||
}, follow=True)
|
||||
self.assertRedirects(response,
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret),
|
||||
target_status_code=200)
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/modify' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), {
|
||||
'%s-question_%s' % (self.ticket_pos.id, self.question.id): 'ABC',
|
||||
'zipcode': '12345',
|
||||
'street': 'Main Street',
|
||||
'city': 'Heidelberg',
|
||||
'country': 'DE',
|
||||
'transmission_type': 'email',
|
||||
}, follow=True)
|
||||
self.assertRedirects(response,
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret),
|
||||
target_status_code=200)
|
||||
with scopes_disabled():
|
||||
assert self.order.invoices.count() == 3
|
||||
last_two = self.order.invoices.order_by('-pk')[:2]
|
||||
for inv in last_two:
|
||||
assert inv.transmission_status != Invoice.TRANSMISSION_STATUS_PENDING
|
||||
|
||||
self.event.settings.set('invoice_reissue_after_modify', False)
|
||||
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/modify' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), {
|
||||
'%s-question_%s' % (self.ticket_pos.id, self.question.id): 'ABC',
|
||||
'zipcode': '54321',
|
||||
'street': 'Main Street',
|
||||
'city': 'Heidelberg',
|
||||
'country': 'DE',
|
||||
'transmission_type': 'email',
|
||||
}, follow=True)
|
||||
self.assertRedirects(response,
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret),
|
||||
target_status_code=200)
|
||||
response = self.client.post(
|
||||
'/%s/%s/order/%s/%s/modify' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), {
|
||||
'%s-question_%s' % (self.ticket_pos.id, self.question.id): 'ABC',
|
||||
'zipcode': '54321',
|
||||
'street': 'Main Street',
|
||||
'city': 'Heidelberg',
|
||||
'country': 'DE',
|
||||
'transmission_type': 'email',
|
||||
}, follow=True)
|
||||
self.assertRedirects(response,
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret),
|
||||
target_status_code=200)
|
||||
with scopes_disabled():
|
||||
assert self.order.invoices.count() == 3
|
||||
|
||||
|
||||
Reference in new issue
Block a user