mirror of
https://github.com/pretix/pretix.git
synced 2025-12-18 16:12:26 +00:00
Compare commits
1 Commits
master
...
datasync-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c74116b73 |
@@ -1,7 +1,7 @@
|
|||||||
This file is part of pretix (Community Edition).
|
This file is part of pretix (Community Edition).
|
||||||
|
|
||||||
Copyright (C) 2014-2020 Raphael Michel and contributors
|
Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
Copyright (C) 2020-today pretix GmbH and contributors
|
Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
Public License as published by the Free Software Foundation in version 3 of the License.
|
Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -421,94 +421,3 @@ Annulment of a check-in
|
|||||||
:statuscode 401: Authentication failure
|
:statuscode 401: Authentication failure
|
||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||||
:statuscode 404: The requested nonce does not exist.
|
:statuscode 404: The requested nonce does not exist.
|
||||||
|
|
||||||
|
|
||||||
Check-in history
|
|
||||||
----------------
|
|
||||||
|
|
||||||
.. rst-class:: rest-resource-table
|
|
||||||
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
Field Type Description
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
id integer Internal ID of the check-in
|
|
||||||
successful boolean Whether the check-in was successful
|
|
||||||
error_reason string Category of reason why the check-in was unsuccessful. Currently
|
|
||||||
``"canceled"``, ``"invalid"``, ``"unpaid"`` ``"product"``,
|
|
||||||
``"rules"``, ``"revoked"``, ``"incomplete"``, ``"already_redeemed"``,
|
|
||||||
``"ambiguous"``, ``"error"``, ``"blocked"``, ``"unapproved"``,
|
|
||||||
``"invalid_time"``, ``"annulled"`` or ``null``
|
|
||||||
error_explanation string Additional, human-readable reason for the check-in to be unsuccessful (or ``null``)
|
|
||||||
position integer Internal ID of the order position (or ``null`` for unknown scans)
|
|
||||||
datetime datetime Logical time when the check-in happened
|
|
||||||
created datetime Time when the check-in appeared on the server
|
|
||||||
list integer Internal ID of the check-in list
|
|
||||||
auto_checked_in boolean Whether the check-in was performed by the system automatically
|
|
||||||
gate integer Internal ID of the gate (or ``null``)
|
|
||||||
device integer Internal ID of the device (or ``null``)
|
|
||||||
device_id integer Organizer-internal ID of the device (or ``null``)
|
|
||||||
type string Type of check-in, currently ``"entry"`` or ``"exit"``
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
|
|
||||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkins/
|
|
||||||
|
|
||||||
Returns a list of all check-in events within a given event.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkins/ 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,
|
|
||||||
"successful": true,
|
|
||||||
"error_reason": null,
|
|
||||||
"error_explanation": null,
|
|
||||||
"position": 1234,
|
|
||||||
"datetime": "2017-12-25T12:45:23Z",
|
|
||||||
"created": "2017-12-25T12:45:23Z",
|
|
||||||
"list": 2,
|
|
||||||
"auto_checked_in": false,
|
|
||||||
"gate": null,
|
|
||||||
"device": null,
|
|
||||||
"device_id": null,
|
|
||||||
"type": "entry",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
|
||||||
:query datetime created_since: Only return check-ins that have been created since the given date (inclusive).
|
|
||||||
:query datetime created_before: Only return check-ins that have been created before the given date (exclusive).
|
|
||||||
:query datetime datetime_since: Only return check-ins that have happened since the given date (inclusive).
|
|
||||||
:query datetime datetime_before: Only return check-ins that have happened before the given date (exclusive).
|
|
||||||
:query boolean successful: Only return check-ins that have (not) been successful.
|
|
||||||
:query boolean error_reason: Only return check-ins with a specific error reason.
|
|
||||||
:query integer list: Only return check-ins from a specific list.
|
|
||||||
:query string type: Only return check-ins of a specific type.
|
|
||||||
:query integer gate: Only return check-ins from a specific gate.
|
|
||||||
:query integer device: Only return check-ins from a specific device.
|
|
||||||
:query boolean auto_checked_in: Only return check-ins that are (not) auto-checked in.
|
|
||||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``created``,
|
|
||||||
and ``id``.
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
|
||||||
:param event: The ``slug`` field of the event to fetch
|
|
||||||
:statuscode 200: no error
|
|
||||||
:statuscode 401: Authentication failure
|
|
||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ at :ref:`plugin-docs`.
|
|||||||
item_bundles
|
item_bundles
|
||||||
item_add-ons
|
item_add-ons
|
||||||
item_meta_properties
|
item_meta_properties
|
||||||
item_program_times
|
|
||||||
questions
|
questions
|
||||||
question_options
|
question_options
|
||||||
quotas
|
quotas
|
||||||
|
|||||||
@@ -22,13 +22,10 @@ invoice_from_name string Sender address:
|
|||||||
invoice_from string Sender address: Address lines
|
invoice_from string Sender address: Address lines
|
||||||
invoice_from_zipcode string Sender address: ZIP code
|
invoice_from_zipcode string Sender address: ZIP code
|
||||||
invoice_from_city string Sender address: City
|
invoice_from_city string Sender address: City
|
||||||
invoice_from_state string Sender address: State (only used in some countries)
|
|
||||||
invoice_from_country string Sender address: Country code
|
invoice_from_country string Sender address: Country code
|
||||||
invoice_from_tax_id string Sender address: Local Tax ID
|
invoice_from_tax_id string Sender address: Local Tax ID
|
||||||
invoice_from_vat_id string Sender address: EU VAT ID
|
invoice_from_vat_id string Sender address: EU VAT ID
|
||||||
invoice_to string Full recipient address
|
invoice_to string Full recipient address
|
||||||
invoice_to_is_business boolean Recipient address: Business vs individual (``null`` for
|
|
||||||
invoices created before pretix 2025.6).
|
|
||||||
invoice_to_company string Recipient address: Company name
|
invoice_to_company string Recipient address: Company name
|
||||||
invoice_to_name string Recipient address: Person name
|
invoice_to_name string Recipient address: Person name
|
||||||
invoice_to_street string Recipient address: Address lines
|
invoice_to_street string Recipient address: Address lines
|
||||||
@@ -38,7 +35,6 @@ invoice_to_state string Recipient addre
|
|||||||
invoice_to_country string Recipient address: Country code
|
invoice_to_country string Recipient address: Country code
|
||||||
invoice_to_vat_id string Recipient address: EU VAT ID
|
invoice_to_vat_id string Recipient address: EU VAT ID
|
||||||
invoice_to_beneficiary string Invoice beneficiary
|
invoice_to_beneficiary string Invoice beneficiary
|
||||||
invoice_to_transmission_info object Additional transmission info (see :ref:`rest-transmission-types`)
|
|
||||||
custom_field string Custom invoice address field
|
custom_field string Custom invoice address field
|
||||||
date date Invoice date
|
date date Invoice date
|
||||||
refers string Invoice number of an invoice this invoice refers to
|
refers string Invoice number of an invoice this invoice refers to
|
||||||
@@ -81,12 +77,17 @@ lines list of objects The actual invo
|
|||||||
for all invoice lines
|
for all invoice lines
|
||||||
created before this field was introduced as well as for
|
created before this field was introduced as well as for
|
||||||
all lines not created by a fee (e.g. a product).
|
all lines not created by a fee (e.g. a product).
|
||||||
├ period_start datetime Start date of the service or delivery period of the invoice line.
|
├ event_date_from datetime Start date of the (sub)event this line was created for as it
|
||||||
Can be ``null`` if not known.
|
was set during invoice creation. Can be ``null`` for all invoice
|
||||||
├ period_end datetime End date of the service or delivery period of the invoice line.
|
lines created before this was introduced as well as for lines in
|
||||||
Can be ``null`` if not known.
|
an event series not created by a product (e.g. shipping or
|
||||||
├ event_date_from datetime Deprecated alias of ``period_start``.
|
cancellation fees).
|
||||||
├ event_date_to datetime Deprecated alias of ``period_end``.
|
├ event_date_to datetime End date of the (sub)event this line was created for as it
|
||||||
|
was set during invoice creation. Can be ``null`` for all invoice
|
||||||
|
lines created before this was introduced as well as for lines in
|
||||||
|
an event series not created by a product (e.g. shipping or
|
||||||
|
cancellation fees) as well as whenever the respective (sub)event
|
||||||
|
has no end date set.
|
||||||
├ event_location string Location of the (sub)event this line was created for as it
|
├ event_location string Location of the (sub)event this line was created for as it
|
||||||
was set during invoice creation. Can be ``null`` for all invoice
|
was set during invoice creation. Can be ``null`` for all invoice
|
||||||
lines created before this was introduced as well as for lines in
|
lines created before this was introduced as well as for lines in
|
||||||
@@ -109,12 +110,6 @@ foreign_currency_rate decimal (string) If ``foreign_cu
|
|||||||
foreign_currency_rate_date date If ``foreign_currency_rate`` is set, this signifies the
|
foreign_currency_rate_date date If ``foreign_currency_rate`` is set, this signifies the
|
||||||
date at which the currency rate was obtained.
|
date at which the currency rate was obtained.
|
||||||
internal_reference string Customer's reference to be printed on the invoice.
|
internal_reference string Customer's reference to be printed on the invoice.
|
||||||
transmission_type string Requested transmission channel (see :ref:`rest-transmission-types`)
|
|
||||||
transmission_provider string Selected transmission provider (depends on installed
|
|
||||||
plugins). ``null`` if not yet chosen.
|
|
||||||
transmission_status string Transmission status, one of ``unknown`` (pre-2025.6),
|
|
||||||
``pending``, ``inflight``, ``failed``, and ``completed``.
|
|
||||||
transmission_date datetime Time of last change in transmission status (may be ``null``).
|
|
||||||
===================================== ========================== =======================================================
|
===================================== ========================== =======================================================
|
||||||
|
|
||||||
|
|
||||||
@@ -126,76 +121,6 @@ transmission_date datetime Time of last ch
|
|||||||
|
|
||||||
The ``tax_code`` attribute has been added.
|
The ``tax_code`` attribute has been added.
|
||||||
|
|
||||||
.. versionchanged:: 2025.6
|
|
||||||
|
|
||||||
The attributes ``invoice_to_is_business``, ``invoice_to_transmission_info``, ``transmission_type``,
|
|
||||||
``transmission_provider``, ``transmission_status``, and ``transmission_date`` have been added.
|
|
||||||
|
|
||||||
|
|
||||||
.. _`rest-transmission-types`:
|
|
||||||
|
|
||||||
Transmission types
|
|
||||||
------------------
|
|
||||||
|
|
||||||
pretix supports multiple ways to transmit an invoice from the organizer to the invoice recipient.
|
|
||||||
For each transmission type, different fields are supported in the ``transmission_info`` object of the
|
|
||||||
invoice address. Currently, pretix supports the following transmission types:
|
|
||||||
|
|
||||||
Email
|
|
||||||
"""""
|
|
||||||
|
|
||||||
The identifier ``"email"`` represents the transmission of PDF invoices through email.
|
|
||||||
This is the default transmission type in pretix and has some special behavior for backwards compatibility.
|
|
||||||
Transmission is always executed through the provider ``"email_pdf"``.
|
|
||||||
The ``transmission_info`` object may contain the following properties:
|
|
||||||
|
|
||||||
.. rst-class:: rest-resource-table
|
|
||||||
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
Field Type Description
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
transmission_email_address string Optional. An email address other than the order address
|
|
||||||
that the invoice should be sent to.
|
|
||||||
Business customers only.
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
|
|
||||||
Peppol
|
|
||||||
""""""
|
|
||||||
|
|
||||||
The identifier ``"peppol"`` represents the transmission of XML invoices through the `Peppol`_ network.
|
|
||||||
This is only available for business addresses.
|
|
||||||
This is not supported by pretix out of the box and requires the use of a suitable plugin.
|
|
||||||
The ``transmission_info`` object may contain the following properties:
|
|
||||||
|
|
||||||
.. rst-class:: rest-resource-table
|
|
||||||
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
Field Type Description
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
transmission_peppol_participant_id string Required. The Peppol participant ID of the recipient.
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
|
|
||||||
Italian Exchange System
|
|
||||||
"""""""""""""""""""""""
|
|
||||||
|
|
||||||
The identifier ``"it_sdi"`` represents the transmission of XML invoices through the `Sistema di Interscambio`_ network used in Italy.
|
|
||||||
This is only available for addresses with country ``"IT"``.
|
|
||||||
This is not supported by pretix out of the box and requires the use of a suitable plugin.
|
|
||||||
The ``transmission_info`` object may contain the following properties:
|
|
||||||
|
|
||||||
.. rst-class:: rest-resource-table
|
|
||||||
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
Field Type Description
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
transmission_it_sdi_codice_fiscale string Required for non-business address. Fiscal code of the
|
|
||||||
recipient.
|
|
||||||
transmission_it_sdi_pec string Required for business addresses. Address for certified
|
|
||||||
electronic mail.
|
|
||||||
transmission_it_sdi_recipient_code string Required for businesses. SdI recipient code.
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
|
|
||||||
If this type is selected, ``vat_id`` is required for business addresses.
|
|
||||||
|
|
||||||
List of all invoices
|
List of all invoices
|
||||||
--------------------
|
--------------------
|
||||||
@@ -234,13 +159,11 @@ List of all invoices
|
|||||||
"invoice_from": "Demo street 12",
|
"invoice_from": "Demo street 12",
|
||||||
"invoice_from_zipcode":"",
|
"invoice_from_zipcode":"",
|
||||||
"invoice_from_city":"Demo town",
|
"invoice_from_city":"Demo town",
|
||||||
"invoice_from_state":"CA",
|
|
||||||
"invoice_from_country":"US",
|
"invoice_from_country":"US",
|
||||||
"invoice_from_tax_id":"",
|
"invoice_from_tax_id":"",
|
||||||
"invoice_from_vat_id":"",
|
"invoice_from_vat_id":"",
|
||||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT-ID: EU123456789",
|
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT-ID: EU123456789",
|
||||||
"invoice_to_company": "Sample company",
|
"invoice_to_company": "Sample company",
|
||||||
"invoice_to_is_business": true,
|
|
||||||
"invoice_to_name": "John Doe",
|
"invoice_to_name": "John Doe",
|
||||||
"invoice_to_street": "Test street 12",
|
"invoice_to_street": "Test street 12",
|
||||||
"invoice_to_zipcode": "12345",
|
"invoice_to_zipcode": "12345",
|
||||||
@@ -249,7 +172,6 @@ List of all invoices
|
|||||||
"invoice_to_country": "TE",
|
"invoice_to_country": "TE",
|
||||||
"invoice_to_vat_id": "EU123456789",
|
"invoice_to_vat_id": "EU123456789",
|
||||||
"invoice_to_beneficiary": "",
|
"invoice_to_beneficiary": "",
|
||||||
"invoice_to_transmission_info": {},
|
|
||||||
"custom_field": null,
|
"custom_field": null,
|
||||||
"date": "2017-12-01",
|
"date": "2017-12-01",
|
||||||
"refers": null,
|
"refers": null,
|
||||||
@@ -271,8 +193,6 @@ List of all invoices
|
|||||||
"fee_internal_type": null,
|
"fee_internal_type": null,
|
||||||
"event_date_from": "2017-12-27T10:00:00Z",
|
"event_date_from": "2017-12-27T10:00:00Z",
|
||||||
"event_date_to": null,
|
"event_date_to": null,
|
||||||
"period_start": "2017-12-27T10:00:00Z",
|
|
||||||
"period_end": "2017-12-27T10:00:00Z",
|
|
||||||
"event_location": "Heidelberg",
|
"event_location": "Heidelberg",
|
||||||
"attendee_name": null,
|
"attendee_name": null,
|
||||||
"gross_value": "23.00",
|
"gross_value": "23.00",
|
||||||
@@ -284,11 +204,7 @@ List of all invoices
|
|||||||
],
|
],
|
||||||
"foreign_currency_display": "PLN",
|
"foreign_currency_display": "PLN",
|
||||||
"foreign_currency_rate": "4.2408",
|
"foreign_currency_rate": "4.2408",
|
||||||
"foreign_currency_rate_date": "2017-07-24",
|
"foreign_currency_rate_date": "2017-07-24"
|
||||||
"transmission_type": "email",
|
|
||||||
"transmission_provider": "email_pdf",
|
|
||||||
"transmission_status": "completed",
|
|
||||||
"transmission_date": "2017-07-24T10:00:00Z"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -383,13 +299,11 @@ Fetching individual invoices
|
|||||||
"invoice_from": "Demo street 12",
|
"invoice_from": "Demo street 12",
|
||||||
"invoice_from_zipcode":"",
|
"invoice_from_zipcode":"",
|
||||||
"invoice_from_city":"Demo town",
|
"invoice_from_city":"Demo town",
|
||||||
"invoice_from_state":"CA",
|
|
||||||
"invoice_from_country":"US",
|
"invoice_from_country":"US",
|
||||||
"invoice_from_tax_id":"",
|
"invoice_from_tax_id":"",
|
||||||
"invoice_from_vat_id":"",
|
"invoice_from_vat_id":"",
|
||||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT-ID: EU123456789",
|
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT-ID: EU123456789",
|
||||||
"invoice_to_company": "Sample company",
|
"invoice_to_company": "Sample company",
|
||||||
"invoice_to_is_business": true,
|
|
||||||
"invoice_to_name": "John Doe",
|
"invoice_to_name": "John Doe",
|
||||||
"invoice_to_street": "Test street 12",
|
"invoice_to_street": "Test street 12",
|
||||||
"invoice_to_zipcode": "12345",
|
"invoice_to_zipcode": "12345",
|
||||||
@@ -398,7 +312,6 @@ Fetching individual invoices
|
|||||||
"invoice_to_country": "TE",
|
"invoice_to_country": "TE",
|
||||||
"invoice_to_vat_id": "EU123456789",
|
"invoice_to_vat_id": "EU123456789",
|
||||||
"invoice_to_beneficiary": "",
|
"invoice_to_beneficiary": "",
|
||||||
"invoice_to_transmission_info": {},
|
|
||||||
"custom_field": null,
|
"custom_field": null,
|
||||||
"date": "2017-12-01",
|
"date": "2017-12-01",
|
||||||
"refers": null,
|
"refers": null,
|
||||||
@@ -420,8 +333,6 @@ Fetching individual invoices
|
|||||||
"fee_internal_type": null,
|
"fee_internal_type": null,
|
||||||
"event_date_from": "2017-12-27T10:00:00Z",
|
"event_date_from": "2017-12-27T10:00:00Z",
|
||||||
"event_date_to": null,
|
"event_date_to": null,
|
||||||
"period_start": "2017-12-27T10:00:00Z",
|
|
||||||
"period_end": "2017-12-27T10:00:00Z",
|
|
||||||
"event_location": "Heidelberg",
|
"event_location": "Heidelberg",
|
||||||
"attendee_name": null,
|
"attendee_name": null,
|
||||||
"gross_value": "23.00",
|
"gross_value": "23.00",
|
||||||
@@ -433,11 +344,7 @@ Fetching individual invoices
|
|||||||
],
|
],
|
||||||
"foreign_currency_display": "PLN",
|
"foreign_currency_display": "PLN",
|
||||||
"foreign_currency_rate": "4.2408",
|
"foreign_currency_rate": "4.2408",
|
||||||
"foreign_currency_rate_date": "2017-07-24",
|
"foreign_currency_rate_date": "2017-07-24"
|
||||||
"transmission_type": "email",
|
|
||||||
"transmission_provider": "email_pdf",
|
|
||||||
"transmission_status": "completed",
|
|
||||||
"transmission_date": "2017-07-24T10:00:00Z"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
:param organizer: The ``slug`` field of the organizer to fetch
|
||||||
@@ -542,70 +449,3 @@ Invoices cannot be edited directly, but the following actions can be triggered:
|
|||||||
:statuscode 400: The invoice has already been canceled
|
:statuscode 400: The invoice has already been canceled
|
||||||
:statuscode 401: Authentication failure
|
:statuscode 401: Authentication failure
|
||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||||
|
|
||||||
|
|
||||||
Transmitting invoices
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Invoices are transmitted automatically when created during order creation or payment receipt,
|
|
||||||
but in other cases transmission may need to be triggered manually.
|
|
||||||
|
|
||||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/transmit/
|
|
||||||
|
|
||||||
Transmits the invoice to the recipient, but only if it is in ``pending`` state.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/transmit/ HTTP/1.1
|
|
||||||
Host: pretix.eu
|
|
||||||
Accept: application/json, text/javascript
|
|
||||||
|
|
||||||
**Example response**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
HTTP/1.1 204 No Content
|
|
||||||
Vary: Accept
|
|
||||||
Content-Type: application/pdf
|
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
|
||||||
:param event: The ``slug`` field of the event to fetch
|
|
||||||
:param number: The ``number`` field of the invoice to transmit
|
|
||||||
:statuscode 200: no error
|
|
||||||
:statuscode 401: Authentication failure
|
|
||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to transmit this invoice **or** the invoice may not be transmitted
|
|
||||||
:statuscode 409: The invoice is currently in transmission
|
|
||||||
|
|
||||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/retransmit/
|
|
||||||
|
|
||||||
Transmits the invoice to the recipient even if transmission was already attempted previously.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/retransmit/ HTTP/1.1
|
|
||||||
Host: pretix.eu
|
|
||||||
Accept: application/json, text/javascript
|
|
||||||
|
|
||||||
**Example response**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
HTTP/1.1 204 No Content
|
|
||||||
Vary: Accept
|
|
||||||
Content-Type: application/pdf
|
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
|
||||||
:param event: The ``slug`` field of the event to fetch
|
|
||||||
:param number: The ``number`` field of the invoice to transmit
|
|
||||||
:statuscode 200: no error
|
|
||||||
:statuscode 401: Authentication failure
|
|
||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to transmit this invoice **or** the invoice may not be transmitted
|
|
||||||
:statuscode 409: The invoice is currently in transmission
|
|
||||||
|
|
||||||
|
|
||||||
.. _Peppol: https://en.wikipedia.org/wiki/PEPPOL
|
|
||||||
.. _Sistema di Interscambio: https://it.wikipedia.org/wiki/Fattura_elettronica_in_Italia
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
Item program times
|
|
||||||
==================
|
|
||||||
|
|
||||||
Resource description
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Program times for products (items) that can be set in addition to event times, e.g. to display seperate schedules within an event.
|
|
||||||
Note that ``program_times`` are not available for items inside event series.
|
|
||||||
The program times resource contains the following public fields:
|
|
||||||
|
|
||||||
.. rst-class:: rest-resource-table
|
|
||||||
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
Field Type Description
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
id integer Internal ID of the program time
|
|
||||||
start datetime The start date time for this program time slot.
|
|
||||||
end datetime The end date time for this program time slot.
|
|
||||||
===================================== ========================== =======================================================
|
|
||||||
|
|
||||||
.. versionchanged:: TODO
|
|
||||||
|
|
||||||
The resource has been added.
|
|
||||||
|
|
||||||
|
|
||||||
Endpoints
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/
|
|
||||||
|
|
||||||
Returns a list of all program times for a given item.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/11/program_times/ 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": 3,
|
|
||||||
"next": null,
|
|
||||||
"previous": null,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"start": "2025-08-14T22:00:00Z",
|
|
||||||
"end": "2025-08-15T00:00:00Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"start": "2025-08-12T22:00:00Z",
|
|
||||||
"end": "2025-08-13T22:00:00Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 14,
|
|
||||||
"start": "2025-08-15T22:00:00Z",
|
|
||||||
"end": "2025-08-17T22:00:00Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
|
||||||
:param event: The ``slug`` field of the event to fetch
|
|
||||||
:param item: The ``id`` field of the item to fetch
|
|
||||||
:statuscode 200: no error
|
|
||||||
:statuscode 401: Authentication failure
|
|
||||||
:statuscode 403: The requested organizer/event/item does not exist **or** you have no permission to view this resource.
|
|
||||||
|
|
||||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/(id)/
|
|
||||||
|
|
||||||
Returns information on one program time, identified by its ID.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/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,
|
|
||||||
"start": "2025-08-15T22:00:00Z",
|
|
||||||
"end": "2025-10-27T23:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
|
||||||
:param event: The ``slug`` field of the event to fetch
|
|
||||||
:param item: The ``id`` field of the item to fetch
|
|
||||||
:param id: The ``id`` field of the program time 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)/items/(item)/program_times/
|
|
||||||
|
|
||||||
Creates a new program time
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
POST /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/ HTTP/1.1
|
|
||||||
Host: pretix.eu
|
|
||||||
Accept: application/json, text/javascript
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"start": "2025-08-15T10:00:00Z",
|
|
||||||
"end": "2025-08-15T22:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
**Example response**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
HTTP/1.1 201 Created
|
|
||||||
Vary: Accept
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"id": 17,
|
|
||||||
"start": "2025-08-15T10:00:00Z",
|
|
||||||
"end": "2025-08-15T22:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a program time for
|
|
||||||
:param event: The ``slug`` field of the event to create a program time for
|
|
||||||
:param item: The ``id`` field of the item to create a program time for
|
|
||||||
:statuscode 201: no error
|
|
||||||
:statuscode 400: The program time 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)/items/(item)/program_times/(id)/
|
|
||||||
|
|
||||||
Update a program time. 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/items/1/program_times/1/ HTTP/1.1
|
|
||||||
Host: pretix.eu
|
|
||||||
Accept: application/json, text/javascript
|
|
||||||
Content-Type: application/json
|
|
||||||
Content-Length: 94
|
|
||||||
|
|
||||||
{
|
|
||||||
"start": "2025-08-14T10:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
**Example response**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
HTTP/1.1 200 OK
|
|
||||||
Vary: Accept
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"start": "2025-08-14T10:00:00Z",
|
|
||||||
"end": "2025-08-15T12:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
: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 item to modify
|
|
||||||
:param id: The ``id`` field of the program time to modify
|
|
||||||
:statuscode 200: no error
|
|
||||||
:statuscode 400: The program time 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)/items/(id)/program_times/(id)/
|
|
||||||
|
|
||||||
Delete a program time.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
.. sourcecode:: http
|
|
||||||
|
|
||||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/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 item to modify
|
|
||||||
:param id: The ``id`` field of the program time 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.
|
|
||||||
@@ -139,10 +139,6 @@ has_variations boolean Shows whether
|
|||||||
variations list of objects A list with one object for each variation of this item.
|
variations list of objects A list with one object for each variation of this item.
|
||||||
Can be empty. Only writable during creation,
|
Can be empty. Only writable during creation,
|
||||||
use separate endpoint to modify this later.
|
use separate endpoint to modify this later.
|
||||||
program_times list of objects A list with one object for each program time of this item.
|
|
||||||
Can be empty. Only writable during creation,
|
|
||||||
use separate endpoint to modify this later.
|
|
||||||
Not available for items in event series.
|
|
||||||
├ id integer Internal ID of the variation
|
├ id integer Internal ID of the variation
|
||||||
├ value multi-lingual string The "name" of the variation
|
├ value multi-lingual string The "name" of the variation
|
||||||
├ default_price money (string) The price set directly for this variation or ``null``
|
├ default_price money (string) The price set directly for this variation or ``null``
|
||||||
@@ -229,10 +225,6 @@ meta_data object Values set fo
|
|||||||
|
|
||||||
The ``hidden_if_item_available_mode`` attributes has been added.
|
The ``hidden_if_item_available_mode`` attributes has been added.
|
||||||
|
|
||||||
.. versionchanged:: 2025.9
|
|
||||||
|
|
||||||
The ``program_times`` attribute has been added.
|
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@@ -240,11 +232,9 @@ Please note that an item either always has variations or never has. Once created
|
|||||||
change to an item without and vice versa. To create an item with variations ensure that you POST an item with at least
|
change to an item without and vice versa. To create an item with variations ensure that you POST an item with at least
|
||||||
one variation.
|
one variation.
|
||||||
|
|
||||||
Also note that ``variations``, ``bundles``, ``addons`` and ``program_times`` are only supported on ``POST``. To update/delete variations,
|
Also note that ``variations``, ``bundles``, and ``addons`` are only supported on ``POST``. To update/delete variations,
|
||||||
bundles, add-ons and program times please use the dedicated nested endpoints. By design this endpoint does not support ``PATCH`` and ``PUT``
|
bundles, and add-ons please use the dedicated nested endpoints. By design this endpoint does not support ``PATCH`` and ``PUT``
|
||||||
with nested ``variations``, ``bundles``, ``addons`` and/or ``program_times``.
|
with nested ``variations``, ``bundles`` and/or ``addons``.
|
||||||
|
|
||||||
``program_times`` is not available to items in event series.
|
|
||||||
|
|
||||||
Endpoints
|
Endpoints
|
||||||
---------
|
---------
|
||||||
@@ -383,8 +373,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons": [],
|
"addons": [],
|
||||||
"bundles": [],
|
"bundles": []
|
||||||
"program_times": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -536,8 +525,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons": [],
|
"addons": [],
|
||||||
"bundles": [],
|
"bundles": []
|
||||||
"program_times": []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
:param organizer: The ``slug`` field of the organizer to fetch
|
||||||
@@ -665,13 +653,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons": [],
|
"addons": [],
|
||||||
"bundles": [],
|
"bundles": []
|
||||||
"program_times": [
|
|
||||||
{
|
|
||||||
"start": "2025-08-14T22:00:00Z",
|
|
||||||
"end": "2025-08-15T00:00:00Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
@@ -791,13 +773,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons": [],
|
"addons": [],
|
||||||
"bundles": [],
|
"bundles": []
|
||||||
"program_times": [
|
|
||||||
{
|
|
||||||
"start": "2025-08-14T22:00:00Z",
|
|
||||||
"end": "2025-08-15T00:00:00Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||||
@@ -813,9 +789,8 @@ Endpoints
|
|||||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||||
want to change.
|
want to change.
|
||||||
|
|
||||||
You can change all fields of the resource except the ``has_variations``, ``variations``, ``addon`` and the
|
You can change all fields of the resource except the ``has_variations``, ``variations`` and the ``addon`` field. If
|
||||||
``program_times`` field. If you need to update/delete variations, add-ons or program times, please use the nested
|
you need to update/delete variations or add-ons please use the nested dedicated endpoints.
|
||||||
dedicated endpoints.
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
@@ -949,8 +924,7 @@ Endpoints
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons": [],
|
"addons": [],
|
||||||
"bundles": [],
|
"bundles": []
|
||||||
"program_times": []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to modify
|
:param organizer: The ``slug`` field of the organizer to modify
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ expires datetime The order will
|
|||||||
payment_date date **DEPRECATED AND INACCURATE** Date of payment receipt
|
payment_date date **DEPRECATED AND INACCURATE** Date of payment receipt
|
||||||
payment_provider string **DEPRECATED AND INACCURATE** Payment provider used for this order
|
payment_provider string **DEPRECATED AND INACCURATE** Payment provider used for this order
|
||||||
total money (string) Total value of this order
|
total money (string) Total value of this order
|
||||||
tax_rounding_mode string Tax rounding mode, see :ref:`algorithms-rounding`
|
|
||||||
comment string Internal comment on this order
|
comment string Internal comment on this order
|
||||||
api_meta object Meta data for that order. Only available through API, no guarantees
|
api_meta object Meta data for that order. Only available through API, no guarantees
|
||||||
on the content structure. You can use this to save references to your system.
|
on the content structure. You can use this to save references to your system.
|
||||||
@@ -66,16 +65,11 @@ invoice_address object Invoice address
|
|||||||
├ state string Customer state (ISO 3166-2 code). Only supported in
|
├ state string Customer state (ISO 3166-2 code). Only supported in
|
||||||
AU, BR, CA, CN, MY, MX, and US.
|
AU, BR, CA, CN, MY, MX, and US.
|
||||||
├ internal_reference string Customer's internal reference to be printed on the invoice
|
├ internal_reference string Customer's internal reference to be printed on the invoice
|
||||||
|
|
||||||
├ custom_field string Custom invoice address field
|
├ custom_field string Custom invoice address field
|
||||||
├ vat_id string Customer VAT ID
|
├ vat_id string Customer VAT ID
|
||||||
├ vat_id_validated string ``true``, if the VAT ID has been validated against the
|
└ vat_id_validated string ``true``, if the VAT ID has been validated against the
|
||||||
EU VAT service and validation was successful. This only
|
EU VAT service and validation was successful. This only
|
||||||
happens in rare cases.
|
happens in rare cases.
|
||||||
├ transmission_type string Transmission channel for invoice (see also :ref:`rest-transmission-types`).
|
|
||||||
Defaults to ``email``.
|
|
||||||
└ transmission_info object Transmission-channel specific information (or ``null``).
|
|
||||||
See also :ref:`rest-transmission-types`.
|
|
||||||
positions list of objects List of order positions (see below). By default, only
|
positions list of objects List of order positions (see below). By default, only
|
||||||
non-canceled positions are included.
|
non-canceled positions are included.
|
||||||
fees list of objects List of fees included in the order total. By default, only
|
fees list of objects List of fees included in the order total. By default, only
|
||||||
@@ -148,14 +142,6 @@ plugin_data object Additional data
|
|||||||
|
|
||||||
The ``plugin_data`` attribute has been added.
|
The ``plugin_data`` attribute has been added.
|
||||||
|
|
||||||
.. versionchanged:: 2025.6
|
|
||||||
|
|
||||||
The ``invoice_address.transmission_type`` and ``invoice_address.transmission_info`` attributes have been added.
|
|
||||||
|
|
||||||
.. versionchanged:: 2025.10
|
|
||||||
|
|
||||||
The ``tax_rounding_mode`` attribute has been added.
|
|
||||||
|
|
||||||
.. _order-position-resource:
|
.. _order-position-resource:
|
||||||
|
|
||||||
Order position resource
|
Order position resource
|
||||||
@@ -363,7 +349,6 @@ List of all orders
|
|||||||
"payment_provider": "banktransfer",
|
"payment_provider": "banktransfer",
|
||||||
"fees": [],
|
"fees": [],
|
||||||
"total": "23.00",
|
"total": "23.00",
|
||||||
"tax_rounding_mode": "line",
|
|
||||||
"comment": "",
|
"comment": "",
|
||||||
"custom_followup_at": null,
|
"custom_followup_at": null,
|
||||||
"checkin_attention": false,
|
"checkin_attention": false,
|
||||||
@@ -383,9 +368,7 @@ List of all orders
|
|||||||
"state": "",
|
"state": "",
|
||||||
"internal_reference": "",
|
"internal_reference": "",
|
||||||
"vat_id": "EU123456789",
|
"vat_id": "EU123456789",
|
||||||
"vat_id_validated": false,
|
"vat_id_validated": false
|
||||||
"transmission_type": "email",
|
|
||||||
"transmission_info": {}
|
|
||||||
},
|
},
|
||||||
"positions": [
|
"positions": [
|
||||||
{
|
{
|
||||||
@@ -424,7 +407,6 @@ List of all orders
|
|||||||
"seat": null,
|
"seat": null,
|
||||||
"checkins": [
|
"checkins": [
|
||||||
{
|
{
|
||||||
"id": 1337,
|
|
||||||
"list": 44,
|
"list": 44,
|
||||||
"type": "entry",
|
"type": "entry",
|
||||||
"gate": null,
|
"gate": null,
|
||||||
@@ -608,7 +590,6 @@ Fetching individual orders
|
|||||||
"payment_provider": "banktransfer",
|
"payment_provider": "banktransfer",
|
||||||
"fees": [],
|
"fees": [],
|
||||||
"total": "23.00",
|
"total": "23.00",
|
||||||
"tax_rounding_mode": "line",
|
|
||||||
"comment": "",
|
"comment": "",
|
||||||
"api_meta": {},
|
"api_meta": {},
|
||||||
"custom_followup_at": null,
|
"custom_followup_at": null,
|
||||||
@@ -629,9 +610,7 @@ Fetching individual orders
|
|||||||
"state": "",
|
"state": "",
|
||||||
"internal_reference": "",
|
"internal_reference": "",
|
||||||
"vat_id": "EU123456789",
|
"vat_id": "EU123456789",
|
||||||
"vat_id_validated": false,
|
"vat_id_validated": false
|
||||||
"transmission_type": "email",
|
|
||||||
"transmission_info": {}
|
|
||||||
},
|
},
|
||||||
"positions": [
|
"positions": [
|
||||||
{
|
{
|
||||||
@@ -670,7 +649,6 @@ Fetching individual orders
|
|||||||
"seat": null,
|
"seat": null,
|
||||||
"checkins": [
|
"checkins": [
|
||||||
{
|
{
|
||||||
"id": 1337,
|
|
||||||
"list": 44,
|
"list": 44,
|
||||||
"type": "entry",
|
"type": "entry",
|
||||||
"gate": null,
|
"gate": null,
|
||||||
@@ -1018,7 +996,6 @@ Creating orders
|
|||||||
provider will not be called to do anything about this (i.e. if you pass a bank account to a debit provider, *no*
|
provider will not be called to do anything about this (i.e. if you pass a bank account to a debit provider, *no*
|
||||||
charge will be created), this is just informative in case you *handled the payment already*.
|
charge will be created), this is just informative in case you *handled the payment already*.
|
||||||
* ``payment_date`` (optional) – Date and time of the completion of the payment.
|
* ``payment_date`` (optional) – Date and time of the completion of the payment.
|
||||||
* ``tax_rounding_mode`` (optional)
|
|
||||||
* ``comment`` (optional)
|
* ``comment`` (optional)
|
||||||
* ``custom_followup_at`` (optional)
|
* ``custom_followup_at`` (optional)
|
||||||
* ``checkin_attention`` (optional)
|
* ``checkin_attention`` (optional)
|
||||||
@@ -1040,8 +1017,6 @@ Creating orders
|
|||||||
* ``vat_id_validated`` (optional) – If you need support for reverse charge (rarely the case), you need to check
|
* ``vat_id_validated`` (optional) – If you need support for reverse charge (rarely the case), you need to check
|
||||||
yourself if the passed VAT ID is a valid EU VAT ID. In that case, set this to ``true``. Only valid VAT IDs will
|
yourself if the passed VAT ID is a valid EU VAT ID. In that case, set this to ``true``. Only valid VAT IDs will
|
||||||
trigger reverse charge taxation. Don't forget to set ``is_business`` as well!
|
trigger reverse charge taxation. Don't forget to set ``is_business`` as well!
|
||||||
* ``transmission_type`` (optional, defaults to ``email``)
|
|
||||||
* ``transmission_info`` (optional, see also :ref:`rest-transmission-types`)
|
|
||||||
|
|
||||||
* ``positions``
|
* ``positions``
|
||||||
|
|
||||||
@@ -1066,7 +1041,6 @@ Creating orders
|
|||||||
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
||||||
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
|
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
|
||||||
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
|
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
|
||||||
* ``discount`` (optional, only possible if ``price`` is set; attention: if this is set to not-``null`` on any position, automatic calculation of discounts will not run)
|
|
||||||
* ``answers``
|
* ``answers``
|
||||||
|
|
||||||
* ``question``
|
* ``question``
|
||||||
@@ -1643,7 +1617,6 @@ List of all order positions
|
|||||||
"blocked": null,
|
"blocked": null,
|
||||||
"checkins": [
|
"checkins": [
|
||||||
{
|
{
|
||||||
"id": 1337,
|
|
||||||
"list": 44,
|
"list": 44,
|
||||||
"type": "entry",
|
"type": "entry",
|
||||||
"gate": null,
|
"gate": null,
|
||||||
@@ -1772,7 +1745,6 @@ Fetching individual positions
|
|||||||
"seat": null,
|
"seat": null,
|
||||||
"checkins": [
|
"checkins": [
|
||||||
{
|
{
|
||||||
"id": 1337,
|
|
||||||
"list": 44,
|
"list": 44,
|
||||||
"type": "entry",
|
"type": "entry",
|
||||||
"gate": null,
|
"gate": null,
|
||||||
@@ -2517,7 +2489,6 @@ Order payment endpoints
|
|||||||
|
|
||||||
{
|
{
|
||||||
"amount": "23.00",
|
"amount": "23.00",
|
||||||
"comment": "Overpayment",
|
|
||||||
"mark_canceled": false
|
"mark_canceled": false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,6 @@ The following values for ``action_types`` are valid with pretix core:
|
|||||||
* ``pretix.event.added``
|
* ``pretix.event.added``
|
||||||
* ``pretix.event.changed``
|
* ``pretix.event.changed``
|
||||||
* ``pretix.event.deleted``
|
* ``pretix.event.deleted``
|
||||||
* ``pretix.voucher.added``
|
|
||||||
* ``pretix.voucher.changed``
|
|
||||||
* ``pretix.voucher.deleted``
|
|
||||||
* ``pretix.subevent.added``
|
* ``pretix.subevent.added``
|
||||||
* ``pretix.subevent.changed``
|
* ``pretix.subevent.changed``
|
||||||
* ``pretix.subevent.deleted``
|
* ``pretix.subevent.deleted``
|
||||||
|
|||||||
@@ -178,124 +178,3 @@ Flowchart
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
.. image:: /images/cart_pricing.png
|
.. image:: /images/cart_pricing.png
|
||||||
|
|
||||||
|
|
||||||
.. _`algorithms-rounding`:
|
|
||||||
|
|
||||||
Rounding of taxes
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
pretix internally always stores taxes on a per-line level, like this:
|
|
||||||
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
Product Tax rate Net price Tax Gross price
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
Ticket A 19 % 84.03 15.97 100.00
|
|
||||||
Ticket B 19 % 84.03 15.97 100.00
|
|
||||||
Ticket C 19 % 84.03 15.97 100.00
|
|
||||||
Ticket D 19 % 84.03 15.97 100.00
|
|
||||||
Ticket E 19 % 84.03 15.97 100.00
|
|
||||||
Sum 420.15 79.85 500.00
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
|
|
||||||
Whether the net price is computed from the gross price or vice versa is configured on the tax rule and may differ for every line.
|
|
||||||
|
|
||||||
The line-based computation has a few significant advantages:
|
|
||||||
|
|
||||||
- We can report both net and gross prices for every individual ticket.
|
|
||||||
|
|
||||||
- We can report both net and gross prices for every filter imaginable, such as the gross sum of all sales of Ticket A
|
|
||||||
or the net sum of all sales for a specific date in an event series. All numbers will be exact.
|
|
||||||
|
|
||||||
- When splitting the order into two, both net price and gross price are split without any changes in rounding.
|
|
||||||
|
|
||||||
The main disadvantage is that the tax looks "wrong" when computed from the sum. Taking the sum of net prices (420.15)
|
|
||||||
and multiplying it with the tax rate (19%) yields a tax amount of 79.83 (instead of 79.85) and a gross sum of 499.98
|
|
||||||
(instead of 500.00). This becomes a problem when juristictions, data formats, or external systems expect this calculation
|
|
||||||
to work on the level of the entire order. A prominent example is the EN 16931 standard for e-invoicing that
|
|
||||||
does not allow the computation as created by pretix.
|
|
||||||
|
|
||||||
However, calculating the tax rate from the net total has significant disadvantages:
|
|
||||||
|
|
||||||
- It is impossible to guarantee a stable gross price this way, i.e. if you advertise a price of €100 per ticket to
|
|
||||||
consumers, they will be confused when they only need to pay €499.98 for 5 tickets.
|
|
||||||
|
|
||||||
- Some prices are impossible, e.g. you cannot sell a ticket for a gross price of €99.99 at a 19% tax rate, since there
|
|
||||||
is no two-decimal net price that would be computed to a gross price of €99.99.
|
|
||||||
|
|
||||||
- When splitting an order into two, the combined of the new orders is not guaranteed to be the same as the total of the
|
|
||||||
original order. Therefore, additional payments or refunds of very small amounts might be necessary.
|
|
||||||
|
|
||||||
To allow organizers to make their own choices on this matter, pretix provides the following options:
|
|
||||||
|
|
||||||
Compute taxes for every line individually
|
|
||||||
"""""""""""""""""""""""""""""""""""""""""
|
|
||||||
|
|
||||||
Algorithm identifier: ``line``
|
|
||||||
|
|
||||||
This is our original algorithm where the tax value is rounded for every line individually.
|
|
||||||
|
|
||||||
**This is our current default algorithm and we recommend it whenever you do not have different requirements** (see below).
|
|
||||||
For the example above:
|
|
||||||
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
Product Tax rate Net price Tax Gross price
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
Ticket A 19 % 84.03 15.97 100.00
|
|
||||||
Ticket B 19 % 84.03 15.97 100.00
|
|
||||||
Ticket C 19 % 84.03 15.97 100.00
|
|
||||||
Ticket D 19 % 84.03 15.97 100.00
|
|
||||||
Ticket E 19 % 84.03 15.97 100.00
|
|
||||||
Sum 420.15 79.85 500.00
|
|
||||||
========== ========== =========== ======= =============
|
|
||||||
|
|
||||||
|
|
||||||
Compute taxes based on net total
|
|
||||||
""""""""""""""""""""""""""""""""
|
|
||||||
|
|
||||||
Algorithm identifier: ``sum_by_net``
|
|
||||||
|
|
||||||
In this algorithm, the tax value and gross total are computed from the sum of the net prices. To accomplish this within
|
|
||||||
our data model, the gross price and tax of some of the tickets will be changed by the minimum currency unit (e.g. €0.01).
|
|
||||||
The net price of the tickets always stay the same.
|
|
||||||
|
|
||||||
**This is the algorithm intended by EN 16931 invoices and our recommendation to use for e-invoicing when (primarily) business customers are involved.**
|
|
||||||
|
|
||||||
The main downside is that it might be confusing when selling to consumers, since the amounts to be paid change in unexpected ways.
|
|
||||||
For the example above, the customer expects to pay 5 times 100.00, but they are are in fact charged 499.98:
|
|
||||||
|
|
||||||
========== ========== =========== ============================== ==============================
|
|
||||||
Product Tax rate Net price Tax Gross price
|
|
||||||
========== ========== =========== ============================== ==============================
|
|
||||||
Ticket A 19 % 84.03 15.96 (incl. -0.01 rounding) 99.99 (incl. -0.01 rounding)
|
|
||||||
Ticket B 19 % 84.03 15.96 (incl. -0.01 rounding) 99.99 (incl. -0.01 rounding)
|
|
||||||
Ticket C 19 % 84.03 15.97 100.00
|
|
||||||
Ticket D 19 % 84.03 15.97 100.00
|
|
||||||
Ticket E 19 % 84.03 15.97 100.00
|
|
||||||
Sum 420.15 78.83 499.98
|
|
||||||
========== ========== =========== ============================== ==============================
|
|
||||||
|
|
||||||
Compute taxes based on net total with stable gross prices
|
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
|
||||||
|
|
||||||
Algorithm identifier: ``sum_by_net_keep_gross``
|
|
||||||
|
|
||||||
In this algorithm, the tax value and gross total are computed from the sum of the net prices. However, the net prices
|
|
||||||
of some of the tickets will be changed automatically by the minimum currency unit (e.g. €0.01) such that the resulting
|
|
||||||
gross prices stay the same.
|
|
||||||
|
|
||||||
**This is less confusing to consumers and the end result is still compliant to EN 16931, so we recommend this for e-invoicing when (primarily) consumers are involved.**
|
|
||||||
|
|
||||||
The main downside is that it might be confusing when selling to business customers, since the prices of the identical tickets appear to be different.
|
|
||||||
Full computation for the example above:
|
|
||||||
|
|
||||||
========== ========== ============================= ============================== =============
|
|
||||||
Product Tax rate Net price Tax Gross price
|
|
||||||
========== ========== ============================= ============================== =============
|
|
||||||
Ticket A 19 % 84.04 (incl. 0.01 rounding) 15.96 (incl. -0.01 rounding) 100.00
|
|
||||||
Ticket B 19 % 84.04 (incl. 0.01 rounding) 15.96 (incl. -0.01 rounding) 100.00
|
|
||||||
Ticket C 19 % 84.03 15.97 100.00
|
|
||||||
Ticket D 19 % 84.03 15.97 100.00
|
|
||||||
Ticket E 19 % 84.03 15.97 100.00
|
|
||||||
Sum 420.17 79.83 500.00
|
|
||||||
========== ========== ============================= ============================== =============
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ There are multiple signals that will be sent out in the ordering cycle:
|
|||||||
|
|
||||||
.. automodule:: pretix.base.signals
|
.. automodule:: pretix.base.signals
|
||||||
:no-index:
|
:no-index:
|
||||||
:members: validate_cart, validate_cart_addons, validate_order, order_valid_if_pending, order_fee_calculation, order_paid, order_placed, order_canceled, order_reactivated, order_expired, order_expiry_changed, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download, order_split, order_gracefully_delete, build_invoice_data, invoice_line_text
|
:members: validate_cart, validate_cart_addons, validate_order, order_valid_if_pending, order_fee_calculation, order_paid, order_placed, order_canceled, order_reactivated, order_expired, order_expiry_changed, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download, order_split, order_gracefully_delete, invoice_line_text
|
||||||
|
|
||||||
Check-ins
|
Check-ins
|
||||||
"""""""""
|
"""""""""
|
||||||
@@ -37,7 +37,7 @@ Frontend
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head, filter_subevents
|
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head
|
||||||
|
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ Contents:
|
|||||||
email
|
email
|
||||||
placeholder
|
placeholder
|
||||||
invoice
|
invoice
|
||||||
invoicetransmission
|
|
||||||
shredder
|
shredder
|
||||||
import
|
import
|
||||||
customview
|
customview
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
.. highlight:: python
|
|
||||||
:linenothreshold: 5
|
|
||||||
|
|
||||||
Writing an invoice transmission plugin
|
|
||||||
======================================
|
|
||||||
|
|
||||||
An invoice transmission provider transports an invoice from the sender to the recipient.
|
|
||||||
There are pre-defined types of invoice transmission in pretix, currently ``"email"``, ``"peppol"``, and ``"it_sdi"``.
|
|
||||||
You can find more information about them at :ref:`rest-transmission-types`.
|
|
||||||
|
|
||||||
New transmission types can not be added by plugins but need to be added to pretix itself.
|
|
||||||
However, plugins can provide implementations for the actual transmission.
|
|
||||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
|
||||||
|
|
||||||
Output registration
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
New invoice transmission providers can be registered through the :ref:`registry <registries>` mechanism
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from pretix.base.invoicing.transmission import transmission_providers, TransmissionProvider
|
|
||||||
|
|
||||||
@transmission_providers.new()
|
|
||||||
class SdiTransmissionProvider(TransmissionProvider):
|
|
||||||
identifier = "fatturapa_providerabc"
|
|
||||||
type = "it_sdi"
|
|
||||||
verbose_name = _("FatturaPA through provider ABC")
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
The provider class
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. class:: pretix.base.invoicing.transmission.TransmissionProvider
|
|
||||||
|
|
||||||
.. autoattribute:: identifier
|
|
||||||
|
|
||||||
This is an abstract attribute, you **must** override this!
|
|
||||||
|
|
||||||
.. autoattribute:: type
|
|
||||||
|
|
||||||
This is an abstract attribute, you **must** override this!
|
|
||||||
|
|
||||||
.. autoattribute:: verbose_name
|
|
||||||
|
|
||||||
This is an abstract attribute, you **must** override this!
|
|
||||||
|
|
||||||
.. autoattribute:: priority
|
|
||||||
|
|
||||||
.. autoattribute:: testmode_supported
|
|
||||||
|
|
||||||
.. automethod:: is_ready
|
|
||||||
|
|
||||||
This is an abstract method, you **must** override this!
|
|
||||||
|
|
||||||
.. automethod:: is_available
|
|
||||||
|
|
||||||
This is an abstract method, you **must** override this!
|
|
||||||
|
|
||||||
.. automethod:: transmit
|
|
||||||
|
|
||||||
This is an abstract method, you **must** override this!
|
|
||||||
|
|
||||||
.. automethod:: settings_url
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 54 KiB |
@@ -23,7 +23,6 @@ partition "For every cart position" {
|
|||||||
--> "Store as line_price (gross), tax_rate"
|
--> "Store as line_price (gross), tax_rate"
|
||||||
}
|
}
|
||||||
--> "Apply discount engine"
|
--> "Apply discount engine"
|
||||||
--> "Apply tax rounding"
|
|
||||||
--> "Store as price (gross)"
|
--> "Store as price (gross)"
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ sphinxcontrib-images
|
|||||||
sphinxcontrib-jquery
|
sphinxcontrib-jquery
|
||||||
sphinxcontrib-spelling==8.*
|
sphinxcontrib-spelling==8.*
|
||||||
sphinxemoji
|
sphinxemoji
|
||||||
pyenchant==3.3.*
|
pyenchant==3.2.*
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ sphinxcontrib-images
|
|||||||
sphinxcontrib-jquery
|
sphinxcontrib-jquery
|
||||||
sphinxcontrib-spelling==8.*
|
sphinxcontrib-spelling==8.*
|
||||||
sphinxemoji
|
sphinxemoji
|
||||||
pyenchant==3.3.*
|
pyenchant==3.2.*
|
||||||
|
|||||||
@@ -28,24 +28,23 @@ classifiers = [
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arabic-reshaper==3.0.0", # Support for Arabic in reportlab
|
"arabic-reshaper==3.0.0", # Support for Arabic in reportlab
|
||||||
"babel",
|
"babel",
|
||||||
"BeautifulSoup4==4.14.*",
|
"BeautifulSoup4==4.13.*",
|
||||||
"bleach==6.2.*",
|
"bleach==6.2.*",
|
||||||
"celery==5.6.*",
|
"celery==5.5.*",
|
||||||
"chardet==5.2.*",
|
"chardet==5.2.*",
|
||||||
"cryptography>=44.0.0",
|
"cryptography>=44.0.0",
|
||||||
"css-inline==0.18.*",
|
"css-inline==0.17.*",
|
||||||
"defusedcsv>=1.1.0",
|
"defusedcsv>=1.1.0",
|
||||||
"dnspython==2.*",
|
"Django[argon2]==4.2.*,>=4.2.15",
|
||||||
"Django[argon2]==4.2.*,>=4.2.26",
|
|
||||||
"django-bootstrap3==25.2",
|
"django-bootstrap3==25.2",
|
||||||
"django-compressor==4.5.1",
|
"django-compressor==4.5.1",
|
||||||
"django-countries==7.6.*",
|
"django-countries==7.6.*",
|
||||||
"django-filter==25.1",
|
"django-filter==25.1",
|
||||||
"django-formset-js-improved==0.5.0.4",
|
"django-formset-js-improved==0.5.0.3",
|
||||||
"django-formtools==2.5.1",
|
"django-formtools==2.5.1",
|
||||||
"django-hierarkey==2.0.*,>=2.0.1",
|
"django-hierarkey==2.0.*",
|
||||||
"django-hijack==3.7.*",
|
"django-hijack==3.7.*",
|
||||||
"django-i18nfield==1.11.*",
|
"django-i18nfield==1.10.*",
|
||||||
"django-libsass==0.9",
|
"django-libsass==0.9",
|
||||||
"django-localflavor==5.0",
|
"django-localflavor==5.0",
|
||||||
"django-markup",
|
"django-markup",
|
||||||
@@ -62,10 +61,10 @@ dependencies = [
|
|||||||
"importlib_metadata==8.*", # Polyfill, we can probably drop this once we require Python 3.10+
|
"importlib_metadata==8.*", # Polyfill, we can probably drop this once we require Python 3.10+
|
||||||
"isoweek",
|
"isoweek",
|
||||||
"jsonschema",
|
"jsonschema",
|
||||||
"kombu==5.6.*",
|
"kombu==5.5.*",
|
||||||
"libsass==0.23.*",
|
"libsass==0.23.*",
|
||||||
"lxml",
|
"lxml",
|
||||||
"markdown==3.9", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
"markdown==3.8.2", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||||
# We can upgrade markdown again once django-bootstrap3 upgrades or once we drop Python 3.6 and 3.7
|
# We can upgrade markdown again once django-bootstrap3 upgrades or once we drop Python 3.6 and 3.7
|
||||||
"mt-940==4.30.*",
|
"mt-940==4.30.*",
|
||||||
"oauthlib==3.3.*",
|
"oauthlib==3.3.*",
|
||||||
@@ -77,12 +76,12 @@ dependencies = [
|
|||||||
"phonenumberslite==9.0.*",
|
"phonenumberslite==9.0.*",
|
||||||
"Pillow==11.3.*",
|
"Pillow==11.3.*",
|
||||||
"pretix-plugin-build",
|
"pretix-plugin-build",
|
||||||
"protobuf==6.33.*",
|
"protobuf==6.32.*",
|
||||||
"psycopg2-binary",
|
"psycopg2-binary",
|
||||||
"pycountry",
|
"pycountry",
|
||||||
"pycparser==2.23",
|
"pycparser==2.22",
|
||||||
"pycryptodome==3.23.*",
|
"pycryptodome==3.23.*",
|
||||||
"pypdf==6.4.*",
|
"pypdf==6.0.*",
|
||||||
"python-bidi==0.6.*", # Support for Arabic in reportlab
|
"python-bidi==0.6.*", # Support for Arabic in reportlab
|
||||||
"python-dateutil==2.9.*",
|
"python-dateutil==2.9.*",
|
||||||
"pytz",
|
"pytz",
|
||||||
@@ -91,36 +90,37 @@ dependencies = [
|
|||||||
"qrcode==8.2",
|
"qrcode==8.2",
|
||||||
"redis==6.4.*",
|
"redis==6.4.*",
|
||||||
"reportlab==4.4.*",
|
"reportlab==4.4.*",
|
||||||
"requests==2.32.*",
|
"requests==2.31.*",
|
||||||
"sentry-sdk==2.48.*",
|
"sentry-sdk==2.35.*",
|
||||||
"sepaxml==2.7.*",
|
"sepaxml==2.6.*",
|
||||||
"stripe==7.9.*",
|
"stripe==7.9.*",
|
||||||
"text-unidecode==1.*",
|
"text-unidecode==1.*",
|
||||||
"tlds>=2020041600",
|
"tlds>=2020041600",
|
||||||
"tqdm==4.*",
|
"tqdm==4.*",
|
||||||
"ua-parser==1.0.*",
|
"ua-parser==1.0.*",
|
||||||
|
"vat_moss_forked==2020.3.20.0.11.0",
|
||||||
"vobject==0.9.*",
|
"vobject==0.9.*",
|
||||||
"webauthn==2.7.*",
|
"webauthn==2.6.*",
|
||||||
"zeep==4.3.*"
|
"zeep==4.3.*"
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
memcached = ["pylibmc"]
|
memcached = ["pylibmc"]
|
||||||
dev = [
|
dev = [
|
||||||
"aiohttp==3.13.*",
|
"aiohttp==3.12.*",
|
||||||
"coverage",
|
"coverage",
|
||||||
"coveralls",
|
"coveralls",
|
||||||
"fakeredis==2.33.*",
|
"fakeredis==2.31.*",
|
||||||
"flake8==7.3.*",
|
"flake8==7.3.*",
|
||||||
"freezegun",
|
"freezegun",
|
||||||
"isort==6.1.*",
|
"isort==6.0.*",
|
||||||
"pep8-naming==0.15.*",
|
"pep8-naming==0.15.*",
|
||||||
"potypo",
|
"potypo",
|
||||||
"pytest-asyncio>=0.24",
|
"pytest-asyncio>=0.24",
|
||||||
"pytest-cache",
|
"pytest-cache",
|
||||||
"pytest-cov",
|
"pytest-cov",
|
||||||
"pytest-django==4.*",
|
"pytest-django==4.*",
|
||||||
"pytest-mock==3.15.*",
|
"pytest-mock==3.14.*",
|
||||||
"pytest-sugar",
|
"pytest-sugar",
|
||||||
"pytest-xdist==3.8.*",
|
"pytest-xdist==3.8.*",
|
||||||
"pytest==8.4.*",
|
"pytest==8.4.*",
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ coverage:
|
|||||||
coverage run -m py.test
|
coverage run -m py.test
|
||||||
|
|
||||||
npminstall:
|
npminstall:
|
||||||
# keep this in sync with pretix/_build.py!
|
# keep this in sync with setup.py!
|
||||||
mkdir -p pretix/static.dist/node_prefix/
|
mkdir -p pretix/static.dist/node_prefix/
|
||||||
cp -r pretix/static/npm_dir/* pretix/static.dist/node_prefix/
|
cp -r pretix/static/npm_dir/* pretix/static.dist/node_prefix/
|
||||||
npm ci --prefix=pretix/static.dist/node_prefix
|
npm install --prefix=pretix/static.dist/node_prefix
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -19,4 +19,4 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2025.11.0.dev0"
|
__version__ = "2025.7.0.dev0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -39,7 +39,7 @@ def npm_install():
|
|||||||
node_prefix = os.path.join(here, 'static.dist', 'node_prefix')
|
node_prefix = os.path.join(here, 'static.dist', 'node_prefix')
|
||||||
os.makedirs(node_prefix, exist_ok=True)
|
os.makedirs(node_prefix, exist_ok=True)
|
||||||
shutil.copytree(os.path.join(here, 'static', 'npm_dir'), node_prefix, dirs_exist_ok=True)
|
shutil.copytree(os.path.join(here, 'static', 'npm_dir'), node_prefix, dirs_exist_ok=True)
|
||||||
subprocess.check_call('npm ci', shell=True, cwd=node_prefix)
|
subprocess.check_call('npm install', shell=True, cwd=node_prefix)
|
||||||
npm_installed = True
|
npm_installed = True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
# Generated by Django 4.2.24 on 2025-11-14 16:21
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("pretixapi", "0013_alter_webhookcallretry_retry_not_before"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="webhook",
|
|
||||||
name="target_url",
|
|
||||||
field=models.URLField(max_length=1024),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="webhookcall",
|
|
||||||
name="target_url",
|
|
||||||
field=models.URLField(max_length=1024),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -114,7 +114,7 @@ class OAuthRefreshToken(AbstractRefreshToken):
|
|||||||
class WebHook(models.Model):
|
class WebHook(models.Model):
|
||||||
organizer = models.ForeignKey('pretixbase.Organizer', on_delete=models.CASCADE, related_name='webhooks')
|
organizer = models.ForeignKey('pretixbase.Organizer', on_delete=models.CASCADE, related_name='webhooks')
|
||||||
enabled = models.BooleanField(default=True, verbose_name=_("Enable webhook"))
|
enabled = models.BooleanField(default=True, verbose_name=_("Enable webhook"))
|
||||||
target_url = models.URLField(verbose_name=_("Target URL"), max_length=1024)
|
target_url = models.URLField(verbose_name=_("Target URL"), max_length=255)
|
||||||
all_events = models.BooleanField(default=True, verbose_name=_("All events (including newly created ones)"))
|
all_events = models.BooleanField(default=True, verbose_name=_("All events (including newly created ones)"))
|
||||||
limit_events = models.ManyToManyField('pretixbase.Event', verbose_name=_("Limit to events"), blank=True)
|
limit_events = models.ManyToManyField('pretixbase.Event', verbose_name=_("Limit to events"), blank=True)
|
||||||
comment = models.CharField(verbose_name=_("Comment"), max_length=255, null=True, blank=True)
|
comment = models.CharField(verbose_name=_("Comment"), max_length=255, null=True, blank=True)
|
||||||
@@ -140,7 +140,7 @@ class WebHookEventListener(models.Model):
|
|||||||
class WebHookCall(models.Model):
|
class WebHookCall(models.Model):
|
||||||
webhook = models.ForeignKey('WebHook', on_delete=models.CASCADE, related_name='calls')
|
webhook = models.ForeignKey('WebHook', on_delete=models.CASCADE, related_name='calls')
|
||||||
datetime = models.DateTimeField(auto_now_add=True)
|
datetime = models.DateTimeField(auto_now_add=True)
|
||||||
target_url = models.URLField(max_length=1024)
|
target_url = models.URLField(max_length=255)
|
||||||
action_type = models.CharField(max_length=255)
|
action_type = models.CharField(max_length=255)
|
||||||
is_retry = models.BooleanField(default=False)
|
is_retry = models.BooleanField(default=False)
|
||||||
execution_time = models.FloatField(null=True)
|
execution_time = models.FloatField(null=True)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -795,7 +795,6 @@ class EventSettingsSerializer(SettingsSerializer):
|
|||||||
'invoice_address_asked',
|
'invoice_address_asked',
|
||||||
'invoice_address_required',
|
'invoice_address_required',
|
||||||
'invoice_address_vatid',
|
'invoice_address_vatid',
|
||||||
'invoice_address_vatid_required_countries',
|
|
||||||
'invoice_address_company_required',
|
'invoice_address_company_required',
|
||||||
'invoice_address_beneficiary',
|
'invoice_address_beneficiary',
|
||||||
'invoice_address_custom_field',
|
'invoice_address_custom_field',
|
||||||
@@ -806,7 +805,6 @@ class EventSettingsSerializer(SettingsSerializer):
|
|||||||
'invoice_reissue_after_modify',
|
'invoice_reissue_after_modify',
|
||||||
'invoice_include_free',
|
'invoice_include_free',
|
||||||
'invoice_generate',
|
'invoice_generate',
|
||||||
'invoice_period',
|
|
||||||
'invoice_numbers_consecutive',
|
'invoice_numbers_consecutive',
|
||||||
'invoice_numbers_prefix',
|
'invoice_numbers_prefix',
|
||||||
'invoice_numbers_prefix_cancellations',
|
'invoice_numbers_prefix_cancellations',
|
||||||
@@ -821,7 +819,6 @@ class EventSettingsSerializer(SettingsSerializer):
|
|||||||
'invoice_address_from',
|
'invoice_address_from',
|
||||||
'invoice_address_from_zipcode',
|
'invoice_address_from_zipcode',
|
||||||
'invoice_address_from_city',
|
'invoice_address_from_city',
|
||||||
'invoice_address_from_state',
|
|
||||||
'invoice_address_from_country',
|
'invoice_address_from_country',
|
||||||
'invoice_address_from_tax_id',
|
'invoice_address_from_tax_id',
|
||||||
'invoice_address_from_vat_id',
|
'invoice_address_from_vat_id',
|
||||||
@@ -831,7 +828,6 @@ class EventSettingsSerializer(SettingsSerializer):
|
|||||||
'invoice_eu_currencies',
|
'invoice_eu_currencies',
|
||||||
'invoice_logo_image',
|
'invoice_logo_image',
|
||||||
'invoice_renderer_highlight_order_code',
|
'invoice_renderer_highlight_order_code',
|
||||||
'tax_rounding',
|
|
||||||
'cancel_allow_user',
|
'cancel_allow_user',
|
||||||
'cancel_allow_user_until',
|
'cancel_allow_user_until',
|
||||||
'cancel_allow_user_unpaid_keep',
|
'cancel_allow_user_unpaid_keep',
|
||||||
@@ -944,7 +940,6 @@ class DeviceEventSettingsSerializer(EventSettingsSerializer):
|
|||||||
'invoice_address_asked',
|
'invoice_address_asked',
|
||||||
'invoice_address_required',
|
'invoice_address_required',
|
||||||
'invoice_address_vatid',
|
'invoice_address_vatid',
|
||||||
'invoice_address_vatid_required_countries',
|
|
||||||
'invoice_address_company_required',
|
'invoice_address_company_required',
|
||||||
'invoice_address_beneficiary',
|
'invoice_address_beneficiary',
|
||||||
'invoice_address_custom_field',
|
'invoice_address_custom_field',
|
||||||
@@ -955,7 +950,6 @@ class DeviceEventSettingsSerializer(EventSettingsSerializer):
|
|||||||
'invoice_address_from',
|
'invoice_address_from',
|
||||||
'invoice_address_from_zipcode',
|
'invoice_address_from_zipcode',
|
||||||
'invoice_address_from_city',
|
'invoice_address_from_city',
|
||||||
'invoice_address_from_state',
|
|
||||||
'invoice_address_from_country',
|
'invoice_address_from_country',
|
||||||
'invoice_address_from_tax_id',
|
'invoice_address_from_tax_id',
|
||||||
'invoice_address_from_vat_id',
|
'invoice_address_from_vat_id',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -19,16 +19,45 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from pytz import common_timezones
|
from pytz import common_timezones
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
from pretix.api.serializers.forms import form_field_to_serializer_field
|
|
||||||
from pretix.base.exporter import OrganizerLevelExportMixin
|
from pretix.base.exporter import OrganizerLevelExportMixin
|
||||||
from pretix.base.models import ScheduledEventExport, ScheduledOrganizerExport
|
from pretix.base.models import ScheduledEventExport, ScheduledOrganizerExport
|
||||||
from pretix.base.timeframes import SerializerDateFrameField
|
from pretix.base.timeframes import DateFrameField, SerializerDateFrameField
|
||||||
|
|
||||||
|
|
||||||
|
class FormFieldWrapperField(serializers.Field):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.form_field = kwargs.pop('form_field')
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def to_representation(self, value):
|
||||||
|
return self.form_field.widget.format_value(value)
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
d = self.form_field.widget.value_from_datadict({'name': data}, {}, 'name')
|
||||||
|
d = self.form_field.clean(d)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
simple_mappings = (
|
||||||
|
(forms.DateField, serializers.DateField, ()),
|
||||||
|
(forms.TimeField, serializers.TimeField, ()),
|
||||||
|
(forms.SplitDateTimeField, serializers.DateTimeField, ()),
|
||||||
|
(forms.DateTimeField, serializers.DateTimeField, ()),
|
||||||
|
(forms.DecimalField, serializers.DecimalField, ('max_digits', 'decimal_places', 'min_value', 'max_value')),
|
||||||
|
(forms.FloatField, serializers.FloatField, ()),
|
||||||
|
(forms.IntegerField, serializers.IntegerField, ()),
|
||||||
|
(forms.EmailField, serializers.EmailField, ()),
|
||||||
|
(forms.UUIDField, serializers.UUIDField, ()),
|
||||||
|
(forms.URLField, serializers.URLField, ()),
|
||||||
|
(forms.BooleanField, serializers.BooleanField, ()),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SerializerDescriptionField(serializers.Field):
|
class SerializerDescriptionField(serializers.Field):
|
||||||
@@ -52,6 +81,13 @@ class ExporterSerializer(serializers.Serializer):
|
|||||||
input_parameters = SerializerDescriptionField(source='_serializer')
|
input_parameters = SerializerDescriptionField(source='_serializer')
|
||||||
|
|
||||||
|
|
||||||
|
class PrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||||
|
def to_representation(self, value):
|
||||||
|
if isinstance(value, int):
|
||||||
|
return value
|
||||||
|
return super().to_representation(value)
|
||||||
|
|
||||||
|
|
||||||
class JobRunSerializer(serializers.Serializer):
|
class JobRunSerializer(serializers.Serializer):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
ex = kwargs.pop('exporter')
|
ex = kwargs.pop('exporter')
|
||||||
@@ -66,7 +102,59 @@ class JobRunSerializer(serializers.Serializer):
|
|||||||
many=True
|
many=True
|
||||||
)
|
)
|
||||||
for k, v in ex.export_form_fields.items():
|
for k, v in ex.export_form_fields.items():
|
||||||
self.fields[k] = form_field_to_serializer_field(v)
|
for m_from, m_to, m_kwargs in simple_mappings:
|
||||||
|
if isinstance(v, m_from):
|
||||||
|
self.fields[k] = m_to(
|
||||||
|
required=v.required,
|
||||||
|
allow_null=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
**{kwarg: getattr(v, kwargs, None) for kwarg in m_kwargs}
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
if isinstance(v, forms.NullBooleanField):
|
||||||
|
self.fields[k] = serializers.BooleanField(
|
||||||
|
required=v.required,
|
||||||
|
allow_null=True,
|
||||||
|
validators=v.validators,
|
||||||
|
)
|
||||||
|
if isinstance(v, forms.ModelMultipleChoiceField):
|
||||||
|
self.fields[k] = PrimaryKeyRelatedField(
|
||||||
|
queryset=v.queryset,
|
||||||
|
required=v.required,
|
||||||
|
allow_empty=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
many=True
|
||||||
|
)
|
||||||
|
elif isinstance(v, forms.ModelChoiceField):
|
||||||
|
self.fields[k] = PrimaryKeyRelatedField(
|
||||||
|
queryset=v.queryset,
|
||||||
|
required=v.required,
|
||||||
|
allow_null=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
)
|
||||||
|
elif isinstance(v, forms.MultipleChoiceField):
|
||||||
|
self.fields[k] = serializers.MultipleChoiceField(
|
||||||
|
choices=v.choices,
|
||||||
|
required=v.required,
|
||||||
|
allow_empty=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
)
|
||||||
|
elif isinstance(v, forms.ChoiceField):
|
||||||
|
self.fields[k] = serializers.ChoiceField(
|
||||||
|
choices=v.choices,
|
||||||
|
required=v.required,
|
||||||
|
allow_null=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
)
|
||||||
|
elif isinstance(v, DateFrameField):
|
||||||
|
self.fields[k] = SerializerDateFrameField(
|
||||||
|
required=v.required,
|
||||||
|
allow_null=not v.required,
|
||||||
|
validators=v.validators,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.fields[k] = FormFieldWrapperField(form_field=v, required=v.required, allow_null=not v.required)
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
if isinstance(data, QueryDict):
|
if isinstance(data, QueryDict):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is part of pretix (Community Edition).
|
|
||||||
#
|
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
|
||||||
#
|
|
||||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
|
||||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
|
||||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
|
||||||
# this file, see <https://pretix.eu/about/en/license>.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
||||||
# details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
|
||||||
# <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from django import forms
|
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from pretix.base.timeframes import DateFrameField, SerializerDateFrameField
|
|
||||||
|
|
||||||
simple_mappings = (
|
|
||||||
(forms.DateField, serializers.DateField, ()),
|
|
||||||
(forms.TimeField, serializers.TimeField, ()),
|
|
||||||
(forms.SplitDateTimeField, serializers.DateTimeField, ()),
|
|
||||||
(forms.DateTimeField, serializers.DateTimeField, ()),
|
|
||||||
(forms.DecimalField, serializers.DecimalField, ('max_digits', 'decimal_places', 'min_value', 'max_value')),
|
|
||||||
(forms.FloatField, serializers.FloatField, ()),
|
|
||||||
(forms.IntegerField, serializers.IntegerField, ()),
|
|
||||||
(forms.EmailField, serializers.EmailField, ()),
|
|
||||||
(forms.UUIDField, serializers.UUIDField, ()),
|
|
||||||
(forms.URLField, serializers.URLField, ()),
|
|
||||||
(forms.BooleanField, serializers.BooleanField, ()),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
|
||||||
def to_representation(self, value):
|
|
||||||
if isinstance(value, int):
|
|
||||||
return value
|
|
||||||
return super().to_representation(value)
|
|
||||||
|
|
||||||
|
|
||||||
class FormFieldWrapperField(serializers.Field):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.form_field = kwargs.pop('form_field')
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def to_representation(self, value):
|
|
||||||
return self.form_field.widget.format_value(value)
|
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
|
||||||
d = self.form_field.widget.value_from_datadict({'name': data}, {}, 'name')
|
|
||||||
d = self.form_field.clean(d)
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
def form_field_to_serializer_field(field):
|
|
||||||
for m_from, m_to, m_kwargs in simple_mappings:
|
|
||||||
if isinstance(field, m_from):
|
|
||||||
return m_to(
|
|
||||||
required=field.required,
|
|
||||||
allow_null=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
**{kwarg: getattr(field, kwarg, None) for kwarg in m_kwargs}
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(field, forms.NullBooleanField):
|
|
||||||
return serializers.BooleanField(
|
|
||||||
required=field.required,
|
|
||||||
allow_null=True,
|
|
||||||
validators=field.validators,
|
|
||||||
)
|
|
||||||
if isinstance(field, forms.ModelMultipleChoiceField):
|
|
||||||
return PrimaryKeyRelatedField(
|
|
||||||
queryset=field.queryset,
|
|
||||||
required=field.required,
|
|
||||||
allow_empty=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
many=True
|
|
||||||
)
|
|
||||||
elif isinstance(field, forms.ModelChoiceField):
|
|
||||||
return PrimaryKeyRelatedField(
|
|
||||||
queryset=field.queryset,
|
|
||||||
required=field.required,
|
|
||||||
allow_null=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
)
|
|
||||||
elif isinstance(field, forms.MultipleChoiceField):
|
|
||||||
return serializers.MultipleChoiceField(
|
|
||||||
choices=field.choices,
|
|
||||||
required=field.required,
|
|
||||||
allow_empty=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
)
|
|
||||||
elif isinstance(field, forms.ChoiceField):
|
|
||||||
return serializers.ChoiceField(
|
|
||||||
choices=field.choices,
|
|
||||||
required=field.required,
|
|
||||||
allow_null=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
)
|
|
||||||
elif isinstance(field, DateFrameField):
|
|
||||||
return SerializerDateFrameField(
|
|
||||||
required=field.required,
|
|
||||||
allow_null=not field.required,
|
|
||||||
validators=field.validators,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return FormFieldWrapperField(form_field=field, required=field.required, allow_null=not field.required)
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -47,9 +47,8 @@ from pretix.api.serializers.event import MetaDataField
|
|||||||
from pretix.api.serializers.fields import UploadedFileField
|
from pretix.api.serializers.fields import UploadedFileField
|
||||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||||
from pretix.base.models import (
|
from pretix.base.models import (
|
||||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemProgramTime,
|
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemVariation,
|
||||||
ItemVariation, ItemVariationMetaValue, Question, QuestionOption, Quota,
|
ItemVariationMetaValue, Question, QuestionOption, Quota, SalesChannel,
|
||||||
SalesChannel,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -188,12 +187,6 @@ class InlineItemAddOnSerializer(serializers.ModelSerializer):
|
|||||||
'position', 'price_included', 'multi_allowed')
|
'position', 'price_included', 'multi_allowed')
|
||||||
|
|
||||||
|
|
||||||
class InlineItemProgramTimeSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ItemProgramTime
|
|
||||||
fields = ('start', 'end')
|
|
||||||
|
|
||||||
|
|
||||||
class ItemBundleSerializer(serializers.ModelSerializer):
|
class ItemBundleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ItemBundle
|
model = ItemBundle
|
||||||
@@ -219,37 +212,6 @@ class ItemBundleSerializer(serializers.ModelSerializer):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class ItemProgramTimeSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ItemProgramTime
|
|
||||||
fields = ('id', 'start', 'end')
|
|
||||||
|
|
||||||
def validate(self, data):
|
|
||||||
data = super().validate(data)
|
|
||||||
|
|
||||||
full_data = self.to_internal_value(self.to_representation(self.instance)) if self.instance else {}
|
|
||||||
full_data.update(data)
|
|
||||||
|
|
||||||
start = full_data.get('start')
|
|
||||||
if not start:
|
|
||||||
raise ValidationError(_("The program start must not be empty."))
|
|
||||||
|
|
||||||
end = full_data.get('end')
|
|
||||||
if not end:
|
|
||||||
raise ValidationError(_("The program end must not be empty."))
|
|
||||||
|
|
||||||
if start > end:
|
|
||||||
raise ValidationError(_("The program end must not be before the program start."))
|
|
||||||
|
|
||||||
event = self.context['event']
|
|
||||||
if event.has_subevents:
|
|
||||||
raise ValidationError({
|
|
||||||
_("You cannot use program times on an event series.")
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
class ItemAddOnSerializer(serializers.ModelSerializer):
|
class ItemAddOnSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ItemAddOn
|
model = ItemAddOn
|
||||||
@@ -288,7 +250,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
addons = InlineItemAddOnSerializer(many=True, required=False)
|
addons = InlineItemAddOnSerializer(many=True, required=False)
|
||||||
bundles = InlineItemBundleSerializer(many=True, required=False)
|
bundles = InlineItemBundleSerializer(many=True, required=False)
|
||||||
variations = InlineItemVariationSerializer(many=True, required=False)
|
variations = InlineItemVariationSerializer(many=True, required=False)
|
||||||
program_times = InlineItemProgramTimeSerializer(many=True, required=False)
|
|
||||||
tax_rate = ItemTaxRateField(source='*', read_only=True)
|
tax_rate = ItemTaxRateField(source='*', read_only=True)
|
||||||
meta_data = MetaDataField(required=False, source='*')
|
meta_data = MetaDataField(required=False, source='*')
|
||||||
picture = UploadedFileField(required=False, allow_null=True, allowed_types=(
|
picture = UploadedFileField(required=False, allow_null=True, allowed_types=(
|
||||||
@@ -310,7 +271,7 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
|
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
|
||||||
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
|
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
|
||||||
'min_per_order', 'max_per_order', 'checkin_attention', 'checkin_text', 'has_variations', 'variations',
|
'min_per_order', 'max_per_order', 'checkin_attention', 'checkin_text', 'has_variations', 'variations',
|
||||||
'addons', 'bundles', 'program_times', 'original_price', 'require_approval', 'generate_tickets',
|
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
|
||||||
'show_quota_left', 'hidden_if_available', 'hidden_if_item_available', 'hidden_if_item_available_mode', 'allow_waitinglist',
|
'show_quota_left', 'hidden_if_available', 'hidden_if_item_available', 'hidden_if_item_available_mode', 'allow_waitinglist',
|
||||||
'issue_giftcard', 'meta_data',
|
'issue_giftcard', 'meta_data',
|
||||||
'require_membership', 'require_membership_types', 'require_membership_hidden', 'grant_membership_type',
|
'require_membership', 'require_membership_types', 'require_membership_hidden', 'grant_membership_type',
|
||||||
@@ -333,9 +294,9 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
data = super().validate(data)
|
data = super().validate(data)
|
||||||
if self.instance and ('addons' in data or 'variations' in data or 'bundles' in data or 'program_times' in data):
|
if self.instance and ('addons' in data or 'variations' in data or 'bundles' in data):
|
||||||
raise ValidationError(_('Updating add-ons, bundles, program times or variations via PATCH/PUT is not '
|
raise ValidationError(_('Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use the '
|
||||||
'supported. Please use the dedicated nested endpoint.'))
|
'dedicated nested endpoint.'))
|
||||||
|
|
||||||
Item.clean_per_order(data.get('min_per_order'), data.get('max_per_order'))
|
Item.clean_per_order(data.get('min_per_order'), data.get('max_per_order'))
|
||||||
Item.clean_available(data.get('available_from'), data.get('available_until'))
|
Item.clean_available(data.get('available_from'), data.get('available_until'))
|
||||||
@@ -386,13 +347,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
ItemAddOn.clean_max_min_count(addon_data.get('max_count', 0), addon_data.get('min_count', 0))
|
ItemAddOn.clean_max_min_count(addon_data.get('max_count', 0), addon_data.get('min_count', 0))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def validate_program_times(self, value):
|
|
||||||
if not self.instance:
|
|
||||||
for program_time_data in value:
|
|
||||||
ItemProgramTime.clean_start_end(self, start=program_time_data.get('start', None),
|
|
||||||
end=program_time_data.get('end', None))
|
|
||||||
return value
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def item_meta_properties(self):
|
def item_meta_properties(self):
|
||||||
return {
|
return {
|
||||||
@@ -410,7 +364,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
variations_data = validated_data.pop('variations') if 'variations' in validated_data else {}
|
variations_data = validated_data.pop('variations') if 'variations' in validated_data else {}
|
||||||
addons_data = validated_data.pop('addons') if 'addons' in validated_data else {}
|
addons_data = validated_data.pop('addons') if 'addons' in validated_data else {}
|
||||||
bundles_data = validated_data.pop('bundles') if 'bundles' in validated_data else {}
|
bundles_data = validated_data.pop('bundles') if 'bundles' in validated_data else {}
|
||||||
program_times_data = validated_data.pop('program_times') if 'program_times' in validated_data else {}
|
|
||||||
meta_data = validated_data.pop('meta_data', None)
|
meta_data = validated_data.pop('meta_data', None)
|
||||||
picture = validated_data.pop('picture', None)
|
picture = validated_data.pop('picture', None)
|
||||||
require_membership_types = validated_data.pop('require_membership_types', [])
|
require_membership_types = validated_data.pop('require_membership_types', [])
|
||||||
@@ -445,8 +398,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
ItemAddOn.objects.create(base_item=item, **addon_data)
|
ItemAddOn.objects.create(base_item=item, **addon_data)
|
||||||
for bundle_data in bundles_data:
|
for bundle_data in bundles_data:
|
||||||
ItemBundle.objects.create(base_item=item, **bundle_data)
|
ItemBundle.objects.create(base_item=item, **bundle_data)
|
||||||
for program_time_data in program_times_data:
|
|
||||||
ItemProgramTime.objects.create(item=item, **program_time_data)
|
|
||||||
|
|
||||||
# Meta data
|
# Meta data
|
||||||
if meta_data is not None:
|
if meta_data is not None:
|
||||||
@@ -599,7 +550,7 @@ class QuestionSerializer(I18nAwareModelSerializer):
|
|||||||
if full_data.get('show_during_checkin') and full_data.get('type') in Question.SHOW_DURING_CHECKIN_UNSUPPORTED:
|
if full_data.get('show_during_checkin') and full_data.get('type') in Question.SHOW_DURING_CHECKIN_UNSUPPORTED:
|
||||||
raise ValidationError(_('This type of question cannot be shown during check-in.'))
|
raise ValidationError(_('This type of question cannot be shown during check-in.'))
|
||||||
|
|
||||||
Question.clean_items(event, full_data.get('items') or [])
|
Question.clean_items(event, full_data.get('items'))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def validate_options(self, value):
|
def validate_options(self, value):
|
||||||
@@ -615,7 +566,7 @@ class QuestionSerializer(I18nAwareModelSerializer):
|
|||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
options_data = validated_data.pop('options') if 'options' in validated_data else []
|
options_data = validated_data.pop('options') if 'options' in validated_data else []
|
||||||
items = validated_data.pop('items', [])
|
items = validated_data.pop('items')
|
||||||
|
|
||||||
question = Question.objects.create(**validated_data)
|
question = Question.objects.create(**validated_data)
|
||||||
question.items.set(items)
|
question.items.set(items)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -42,7 +42,6 @@ from rest_framework.reverse import reverse
|
|||||||
|
|
||||||
from pretix.api.serializers import CompatibleJSONField
|
from pretix.api.serializers import CompatibleJSONField
|
||||||
from pretix.api.serializers.event import SubEventSerializer
|
from pretix.api.serializers.event import SubEventSerializer
|
||||||
from pretix.api.serializers.forms import form_field_to_serializer_field
|
|
||||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||||
from pretix.api.serializers.item import (
|
from pretix.api.serializers.item import (
|
||||||
InlineItemVariationSerializer, ItemSerializer, QuestionSerializer,
|
InlineItemVariationSerializer, ItemSerializer, QuestionSerializer,
|
||||||
@@ -50,12 +49,10 @@ from pretix.api.serializers.item import (
|
|||||||
from pretix.api.signals import order_api_details, orderposition_api_details
|
from pretix.api.signals import order_api_details, orderposition_api_details
|
||||||
from pretix.base.decimal import round_decimal
|
from pretix.base.decimal import round_decimal
|
||||||
from pretix.base.i18n import language
|
from pretix.base.i18n import language
|
||||||
from pretix.base.invoicing.transmission import get_transmission_types
|
|
||||||
from pretix.base.models import (
|
from pretix.base.models import (
|
||||||
CachedFile, Checkin, Customer, Device, Invoice, InvoiceAddress,
|
CachedFile, Checkin, Customer, Invoice, InvoiceAddress, InvoiceLine, Item,
|
||||||
InvoiceLine, Item, ItemVariation, Order, OrderPosition, Question,
|
ItemVariation, Order, OrderPosition, Question, QuestionAnswer,
|
||||||
QuestionAnswer, ReusableMedium, SalesChannel, Seat, SubEvent, TaxRule,
|
ReusableMedium, SalesChannel, Seat, SubEvent, TaxRule, Voucher,
|
||||||
Voucher,
|
|
||||||
)
|
)
|
||||||
from pretix.base.models.orders import (
|
from pretix.base.models.orders import (
|
||||||
BlockedTicketSecret, CartPosition, OrderFee, OrderPayment, OrderRefund,
|
BlockedTicketSecret, CartPosition, OrderFee, OrderPayment, OrderRefund,
|
||||||
@@ -65,13 +62,10 @@ from pretix.base.pdf import get_images, get_variables
|
|||||||
from pretix.base.services.cart import error_messages
|
from pretix.base.services.cart import error_messages
|
||||||
from pretix.base.services.locking import LOCK_TRUST_WINDOW, lock_objects
|
from pretix.base.services.locking import LOCK_TRUST_WINDOW, lock_objects
|
||||||
from pretix.base.services.pricing import (
|
from pretix.base.services.pricing import (
|
||||||
apply_discounts, apply_rounding, get_line_price, get_listed_price,
|
apply_discounts, get_line_price, get_listed_price, is_included_for_free,
|
||||||
is_included_for_free,
|
|
||||||
)
|
)
|
||||||
from pretix.base.services.quotas import QuotaAvailability
|
from pretix.base.services.quotas import QuotaAvailability
|
||||||
from pretix.base.settings import (
|
from pretix.base.settings import COUNTRIES_WITH_STATE_IN_ADDRESS
|
||||||
COUNTRIES_WITH_STATE_IN_ADDRESS, ROUNDING_MODES,
|
|
||||||
)
|
|
||||||
from pretix.base.signals import register_ticket_outputs
|
from pretix.base.signals import register_ticket_outputs
|
||||||
from pretix.helpers.countries import CachedCountries
|
from pretix.helpers.countries import CachedCountries
|
||||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||||
@@ -108,13 +102,6 @@ class CountryField(serializers.Field):
|
|||||||
return str(src) if src else None
|
return str(src) if src else None
|
||||||
|
|
||||||
|
|
||||||
class TransmissionInfoSerializer(serializers.Serializer):
|
|
||||||
def __init__(self, *args, transmission_type, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
for k, v in transmission_type.invoice_address_form_fields.items():
|
|
||||||
self.fields[k] = form_field_to_serializer_field(v)
|
|
||||||
|
|
||||||
|
|
||||||
class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
||||||
country = CompatibleCountryField(source='*')
|
country = CompatibleCountryField(source='*')
|
||||||
name = serializers.CharField(required=False)
|
name = serializers.CharField(required=False)
|
||||||
@@ -122,8 +109,7 @@ class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = InvoiceAddress
|
model = InvoiceAddress
|
||||||
fields = ('last_modified', 'is_business', 'company', 'name', 'name_parts', 'street', 'zipcode', 'city', 'country',
|
fields = ('last_modified', 'is_business', 'company', 'name', 'name_parts', 'street', 'zipcode', 'city', 'country',
|
||||||
'state', 'vat_id', 'vat_id_validated', 'custom_field', 'internal_reference', 'transmission_type',
|
'state', 'vat_id', 'vat_id_validated', 'custom_field', 'internal_reference')
|
||||||
'transmission_info')
|
|
||||||
read_only_fields = ('last_modified',)
|
read_only_fields = ('last_modified',)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -161,48 +147,6 @@ class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
|||||||
{'state': ['"{}" is not a known subdivision of the country "{}".'.format(data.get('state'), cc)]}
|
{'state': ['"{}" is not a known subdivision of the country "{}".'.format(data.get('state'), cc)]}
|
||||||
)
|
)
|
||||||
|
|
||||||
if data.get("transmission_type"):
|
|
||||||
for t in get_transmission_types():
|
|
||||||
if data.get("transmission_type") == t.identifier:
|
|
||||||
if not t.is_available(self.context["request"].event, data.get("country"), data.get("is_business")):
|
|
||||||
raise ValidationError({
|
|
||||||
"transmission_type": "The selected transmission type is not available for this country or address type."
|
|
||||||
})
|
|
||||||
|
|
||||||
ts = TransmissionInfoSerializer(transmission_type=t, data=data.get("transmission_info", {}))
|
|
||||||
try:
|
|
||||||
ts.is_valid(raise_exception=True)
|
|
||||||
except ValidationError as e:
|
|
||||||
raise ValidationError(
|
|
||||||
{"transmission_info": e.detail}
|
|
||||||
)
|
|
||||||
data["transmission_info"] = ts.validated_data
|
|
||||||
|
|
||||||
required_fields = t.invoice_address_form_fields_required(data.get("country"), data.get("is_business"))
|
|
||||||
for r in required_fields:
|
|
||||||
if r in self.fields:
|
|
||||||
if not data.get(r):
|
|
||||||
raise ValidationError(
|
|
||||||
{r: "This field is required for the selected type of invoice transmission."}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if not ts.validated_data.get(r):
|
|
||||||
raise ValidationError(
|
|
||||||
{"transmission_info": {r: "This field is required for the selected type of invoice transmission."}}
|
|
||||||
)
|
|
||||||
break # do not call else branch of for loop
|
|
||||||
elif t.exclusive:
|
|
||||||
if t.is_available(self.context["request"].event, data.get("country"), data.get("is_business")):
|
|
||||||
raise ValidationError({
|
|
||||||
"transmission_type": "The transmission type '%s' must be used for this country or address type." % (
|
|
||||||
t.identifier,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
raise ValidationError(
|
|
||||||
{"transmission_type": "Unknown transmission type."}
|
|
||||||
)
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@@ -329,18 +273,6 @@ class AnswerSerializer(I18nAwareModelSerializer):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class InlineCheckinSerializer(I18nAwareModelSerializer):
|
|
||||||
device_id = serializers.SlugRelatedField(
|
|
||||||
source='device',
|
|
||||||
slug_field='device_id',
|
|
||||||
read_only=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Checkin
|
|
||||||
fields = ('id', 'datetime', 'list', 'auto_checked_in', 'gate', 'device', 'device_id', 'type')
|
|
||||||
|
|
||||||
|
|
||||||
class CheckinSerializer(I18nAwareModelSerializer):
|
class CheckinSerializer(I18nAwareModelSerializer):
|
||||||
device_id = serializers.SlugRelatedField(
|
device_id = serializers.SlugRelatedField(
|
||||||
source='device',
|
source='device',
|
||||||
@@ -350,10 +282,7 @@ class CheckinSerializer(I18nAwareModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Checkin
|
model = Checkin
|
||||||
fields = (
|
fields = ('id', 'datetime', 'list', 'auto_checked_in', 'gate', 'device', 'device_id', 'type')
|
||||||
'id', 'successful', 'error_reason', 'error_explanation', 'position', 'datetime', 'list', 'created',
|
|
||||||
'auto_checked_in', 'gate', 'device', 'device_id', 'type'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PrintLogSerializer(serializers.ModelSerializer):
|
class PrintLogSerializer(serializers.ModelSerializer):
|
||||||
@@ -579,7 +508,7 @@ class OrderPositionPluginDataField(serializers.Field):
|
|||||||
|
|
||||||
|
|
||||||
class OrderPositionSerializer(I18nAwareModelSerializer):
|
class OrderPositionSerializer(I18nAwareModelSerializer):
|
||||||
checkins = InlineCheckinSerializer(many=True, read_only=True)
|
checkins = CheckinSerializer(many=True, read_only=True)
|
||||||
print_logs = PrintLogSerializer(many=True, read_only=True)
|
print_logs = PrintLogSerializer(many=True, read_only=True)
|
||||||
answers = AnswerSerializer(many=True)
|
answers = AnswerSerializer(many=True)
|
||||||
downloads = PositionDownloadsField(source='*', read_only=True)
|
downloads = PositionDownloadsField(source='*', read_only=True)
|
||||||
@@ -852,15 +781,14 @@ class OrderSerializer(I18nAwareModelSerializer):
|
|||||||
list_serializer_class = OrderListSerializer
|
list_serializer_class = OrderListSerializer
|
||||||
fields = (
|
fields = (
|
||||||
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
|
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
|
||||||
'payment_provider', 'fees', 'total', 'tax_rounding_mode', 'comment', 'custom_followup_at', 'invoice_address',
|
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
|
||||||
'positions', 'downloads', 'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds',
|
'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
|
||||||
'require_approval', 'sales_channel', 'url', 'customer', 'valid_if_pending', 'api_meta', 'cancellation_date',
|
'url', 'customer', 'valid_if_pending', 'api_meta', 'cancellation_date', 'plugin_data',
|
||||||
'plugin_data',
|
|
||||||
)
|
)
|
||||||
read_only_fields = (
|
read_only_fields = (
|
||||||
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
|
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
|
||||||
'payment_provider', 'fees', 'total', 'tax_rounding_mode', 'positions', 'downloads', 'customer',
|
'payment_provider', 'fees', 'total', 'positions', 'downloads', 'customer',
|
||||||
'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel', 'cancellation_date',
|
'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel', 'cancellation_date'
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -1025,7 +953,7 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
fields = ('positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
|
fields = ('positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
|
||||||
'company', 'street', 'zipcode', 'city', 'country', 'state', 'is_bundled',
|
'company', 'street', 'zipcode', 'city', 'country', 'state', 'is_bundled',
|
||||||
'secret', 'addon_to', 'subevent', 'answers', 'seat', 'voucher', 'valid_from', 'valid_until',
|
'secret', 'addon_to', 'subevent', 'answers', 'seat', 'voucher', 'valid_from', 'valid_until',
|
||||||
'requested_valid_from', 'use_reusable_medium', 'discount')
|
'requested_valid_from', 'use_reusable_medium')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -1121,10 +1049,6 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
|||||||
{'state': ['"{}" is not a known subdivision of the country "{}".'.format(data.get('state'), cc)]}
|
{'state': ['"{}" is not a known subdivision of the country "{}".'.format(data.get('state'), cc)]}
|
||||||
)
|
)
|
||||||
|
|
||||||
if data.get('price') is None and data.get('discount'):
|
|
||||||
raise ValidationError(
|
|
||||||
{'discount': ['You can only specify a discount if you do the price computation, but price is not set.']}
|
|
||||||
)
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@@ -1179,13 +1103,11 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
queryset=SalesChannel.objects.none(),
|
queryset=SalesChannel.objects.none(),
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
tax_rounding_mode = serializers.ChoiceField(choices=ROUNDING_MODES, allow_null=True, required=False,)
|
|
||||||
locale = serializers.ChoiceField(choices=[], required=False, allow_null=True)
|
locale = serializers.ChoiceField(choices=[], required=False, allow_null=True)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields['positions'].child.fields['voucher'].queryset = self.context['event'].vouchers.all()
|
self.fields['positions'].child.fields['voucher'].queryset = self.context['event'].vouchers.all()
|
||||||
self.fields['positions'].child.fields['discount'].queryset = self.context['event'].discounts.all()
|
|
||||||
self.fields['customer'].queryset = self.context['event'].organizer.customers.all()
|
self.fields['customer'].queryset = self.context['event'].organizer.customers.all()
|
||||||
self.fields['expires'].required = False
|
self.fields['expires'].required = False
|
||||||
self.fields["sales_channel"].queryset = self.context["event"].organizer.sales_channels.all()
|
self.fields["sales_channel"].queryset = self.context["event"].organizer.sales_channels.all()
|
||||||
@@ -1196,7 +1118,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
fields = ('code', 'status', 'testmode', 'email', 'phone', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
|
fields = ('code', 'status', 'testmode', 'email', 'phone', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
|
||||||
'invoice_address', 'positions', 'checkin_attention', 'checkin_text', 'payment_info', 'payment_date',
|
'invoice_address', 'positions', 'checkin_attention', 'checkin_text', 'payment_info', 'payment_date',
|
||||||
'consume_carts', 'force', 'send_email', 'simulate', 'customer', 'custom_followup_at',
|
'consume_carts', 'force', 'send_email', 'simulate', 'customer', 'custom_followup_at',
|
||||||
'require_approval', 'valid_if_pending', 'expires', 'api_meta', 'tax_rounding_mode')
|
'require_approval', 'valid_if_pending', 'expires', 'api_meta')
|
||||||
|
|
||||||
def validate_payment_provider(self, pp):
|
def validate_payment_provider(self, pp):
|
||||||
if pp is None:
|
if pp is None:
|
||||||
@@ -1593,9 +1515,6 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
pos.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
|
pos.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
|
||||||
|
|
||||||
order_positions = [pos_data['__instance'] for pos_data in positions_data]
|
order_positions = [pos_data['__instance'] for pos_data in positions_data]
|
||||||
if not any([p.get("discount") for p in positions_data]):
|
|
||||||
# If any discount is set by the client (i.e. pretixPOS), we do not recalculate but believe the client
|
|
||||||
# to avoid differences in end results.
|
|
||||||
discount_results = apply_discounts(
|
discount_results = apply_discounts(
|
||||||
self.context['event'],
|
self.context['event'],
|
||||||
order.sales_channel,
|
order.sales_channel,
|
||||||
@@ -1722,31 +1641,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
else:
|
else:
|
||||||
f.save()
|
f.save()
|
||||||
|
|
||||||
rounding_mode = validated_data.get("tax_rounding_mode")
|
order.total += sum([f.value for f in fees])
|
||||||
if not rounding_mode:
|
|
||||||
if isinstance(self.context.get("auth"), Device):
|
|
||||||
# Safety fallback to avoid differences in tax reporting
|
|
||||||
brand = self.context.get("auth").software_brand or ""
|
|
||||||
if "pretixPOS" in brand or "pretixKIOSK" in brand:
|
|
||||||
rounding_mode = "line"
|
|
||||||
if not rounding_mode:
|
|
||||||
rounding_mode = self.context["event"].settings.tax_rounding
|
|
||||||
changed = apply_rounding(
|
|
||||||
rounding_mode,
|
|
||||||
self.context["event"].currency,
|
|
||||||
[*pos_map.values(), *fees]
|
|
||||||
)
|
|
||||||
for line in changed:
|
|
||||||
if isinstance(line, OrderPosition):
|
|
||||||
line.save(update_fields=[
|
|
||||||
"price", "price_includes_rounding_correction", "tax_value", "tax_value_includes_rounding_correction"
|
|
||||||
])
|
|
||||||
elif isinstance(line, OrderFee):
|
|
||||||
line.save(update_fields=[
|
|
||||||
"value", "value_includes_rounding_correction", "tax_value", "tax_value_includes_rounding_correction"
|
|
||||||
])
|
|
||||||
|
|
||||||
order.total = sum([c.price for c in pos_map.values()]) + sum([f.value for f in fees])
|
|
||||||
if simulate:
|
if simulate:
|
||||||
order.fees = fees
|
order.fees = fees
|
||||||
order.positions = pos_map.values()
|
order.positions = pos_map.values()
|
||||||
@@ -1810,14 +1705,12 @@ class LinePositionField(serializers.IntegerField):
|
|||||||
|
|
||||||
class InlineInvoiceLineSerializer(I18nAwareModelSerializer):
|
class InlineInvoiceLineSerializer(I18nAwareModelSerializer):
|
||||||
position = LinePositionField(read_only=True)
|
position = LinePositionField(read_only=True)
|
||||||
event_date_from = serializers.DateTimeField(read_only=True, source="period_start")
|
|
||||||
event_date_to = serializers.DateTimeField(read_only=True, source="period_end")
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = InvoiceLine
|
model = InvoiceLine
|
||||||
fields = ('position', 'description', 'item', 'variation', 'subevent', 'attendee_name', 'event_date_from',
|
fields = ('position', 'description', 'item', 'variation', 'subevent', 'attendee_name', 'event_date_from',
|
||||||
'event_date_to', 'period_start', 'period_end', 'gross_value', 'tax_value', 'tax_rate', 'tax_code',
|
'event_date_to', 'gross_value', 'tax_value', 'tax_rate', 'tax_code', 'tax_name', 'fee_type',
|
||||||
'tax_name', 'fee_type', 'fee_internal_type', 'event_location')
|
'fee_internal_type', 'event_location')
|
||||||
|
|
||||||
|
|
||||||
class InvoiceSerializer(I18nAwareModelSerializer):
|
class InvoiceSerializer(I18nAwareModelSerializer):
|
||||||
@@ -1831,14 +1724,13 @@ class InvoiceSerializer(I18nAwareModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Invoice
|
model = Invoice
|
||||||
fields = ('event', 'order', 'number', 'is_cancellation', 'invoice_from', 'invoice_from_name', 'invoice_from_zipcode',
|
fields = ('event', 'order', 'number', 'is_cancellation', 'invoice_from', 'invoice_from_name', 'invoice_from_zipcode',
|
||||||
'invoice_from_city', 'invoice_from_state', 'invoice_from_country', 'invoice_from_tax_id', 'invoice_from_vat_id',
|
'invoice_from_city', 'invoice_from_country', 'invoice_from_tax_id', 'invoice_from_vat_id',
|
||||||
'invoice_to', 'invoice_to_is_business', 'invoice_to_company', 'invoice_to_name', 'invoice_to_street',
|
'invoice_to', 'invoice_to_company', 'invoice_to_name', 'invoice_to_street', 'invoice_to_zipcode',
|
||||||
'invoice_to_zipcode', 'invoice_to_city', 'invoice_to_state', 'invoice_to_country', 'invoice_to_vat_id',
|
'invoice_to_city', 'invoice_to_state', 'invoice_to_country', 'invoice_to_vat_id', 'invoice_to_beneficiary',
|
||||||
'invoice_to_beneficiary', 'invoice_to_transmission_info', 'custom_field', 'date', 'refers', 'locale',
|
'custom_field', 'date', 'refers', 'locale',
|
||||||
'introductory_text', 'additional_text', 'payment_provider_text', 'payment_provider_stamp',
|
'introductory_text', 'additional_text', 'payment_provider_text', 'payment_provider_stamp',
|
||||||
'footer_text', 'lines', 'foreign_currency_display', 'foreign_currency_rate',
|
'footer_text', 'lines', 'foreign_currency_display', 'foreign_currency_rate',
|
||||||
'foreign_currency_rate_date', 'internal_reference', 'transmission_type', 'transmission_provider',
|
'foreign_currency_rate_date', 'internal_reference')
|
||||||
'transmission_status', 'transmission_date')
|
|
||||||
|
|
||||||
|
|
||||||
class OrderPaymentCreateSerializer(I18nAwareModelSerializer):
|
class OrderPaymentCreateSerializer(I18nAwareModelSerializer):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -484,7 +484,6 @@ class OrganizerSettingsSerializer(SettingsSerializer):
|
|||||||
'reusable_media_type_nfc_mf0aes',
|
'reusable_media_type_nfc_mf0aes',
|
||||||
'reusable_media_type_nfc_mf0aes_autocreate_giftcard',
|
'reusable_media_type_nfc_mf0aes_autocreate_giftcard',
|
||||||
'reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency',
|
'reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency',
|
||||||
'reusable_media_type_nfc_mf0aes_random_uid',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -92,7 +92,6 @@ event_router.register(r'taxrules', event.TaxRuleViewSet)
|
|||||||
event_router.register(r'seats', event.SeatViewSet)
|
event_router.register(r'seats', event.SeatViewSet)
|
||||||
event_router.register(r'waitinglistentries', waitinglist.WaitingListViewSet)
|
event_router.register(r'waitinglistentries', waitinglist.WaitingListViewSet)
|
||||||
event_router.register(r'checkinlists', checkin.CheckinListViewSet)
|
event_router.register(r'checkinlists', checkin.CheckinListViewSet)
|
||||||
event_router.register(r'checkins', checkin.CheckinViewSet)
|
|
||||||
event_router.register(r'cartpositions', cart.CartPositionViewSet)
|
event_router.register(r'cartpositions', cart.CartPositionViewSet)
|
||||||
event_router.register(r'scheduled_exports', exporters.ScheduledEventExportViewSet)
|
event_router.register(r'scheduled_exports', exporters.ScheduledEventExportViewSet)
|
||||||
event_router.register(r'exporters', exporters.EventExportersViewSet, basename='exporters')
|
event_router.register(r'exporters', exporters.EventExportersViewSet, basename='exporters')
|
||||||
@@ -112,7 +111,6 @@ item_router = routers.DefaultRouter()
|
|||||||
item_router.register(r'variations', item.ItemVariationViewSet)
|
item_router.register(r'variations', item.ItemVariationViewSet)
|
||||||
item_router.register(r'addons', item.ItemAddOnViewSet)
|
item_router.register(r'addons', item.ItemAddOnViewSet)
|
||||||
item_router.register(r'bundles', item.ItemBundleViewSet)
|
item_router.register(r'bundles', item.ItemBundleViewSet)
|
||||||
item_router.register(r'program_times', item.ItemProgramTimeViewSet)
|
|
||||||
|
|
||||||
order_router = routers.DefaultRouter()
|
order_router = routers.DefaultRouter()
|
||||||
order_router.register(r'payments', order.PaymentViewSet)
|
order_router.register(r'payments', order.PaymentViewSet)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -56,8 +56,7 @@ from pretix.api.serializers.checkin import (
|
|||||||
)
|
)
|
||||||
from pretix.api.serializers.item import QuestionSerializer
|
from pretix.api.serializers.item import QuestionSerializer
|
||||||
from pretix.api.serializers.order import (
|
from pretix.api.serializers.order import (
|
||||||
CheckinListOrderPositionSerializer, CheckinSerializer,
|
CheckinListOrderPositionSerializer, FailedCheckinSerializer,
|
||||||
FailedCheckinSerializer,
|
|
||||||
)
|
)
|
||||||
from pretix.api.views import RichOrderingFilter
|
from pretix.api.views import RichOrderingFilter
|
||||||
from pretix.api.views.order import OrderPositionFilter
|
from pretix.api.views.order import OrderPositionFilter
|
||||||
@@ -97,16 +96,6 @@ with scopes_disabled():
|
|||||||
)
|
)
|
||||||
return queryset.filter(expr)
|
return queryset.filter(expr)
|
||||||
|
|
||||||
class CheckinFilter(FilterSet):
|
|
||||||
created_since = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='gte')
|
|
||||||
created_before = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='lt')
|
|
||||||
datetime_since = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='gte')
|
|
||||||
datetime_before = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='lt')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Checkin
|
|
||||||
fields = ['successful', 'error_reason', 'list', 'type', 'gate', 'device', 'auto_checked_in']
|
|
||||||
|
|
||||||
|
|
||||||
class CheckinListViewSet(viewsets.ModelViewSet):
|
class CheckinListViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = CheckinListSerializer
|
serializer_class = CheckinListSerializer
|
||||||
@@ -1091,25 +1080,3 @@ class CheckinRPCAnnulView(views.APIView):
|
|||||||
checkin_annulled.send(ci.position.order.event, checkin=ci)
|
checkin_annulled.send(ci.position.order.event, checkin=ci)
|
||||||
|
|
||||||
return Response({"status": "ok"}, status=status.HTTP_200_OK)
|
return Response({"status": "ok"}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class CheckinViewSet(viewsets.ReadOnlyModelViewSet):
|
|
||||||
serializer_class = CheckinSerializer
|
|
||||||
queryset = Checkin.all.none()
|
|
||||||
filter_backends = (DjangoFilterBackend, RichOrderingFilter)
|
|
||||||
filterset_class = CheckinFilter
|
|
||||||
ordering = ('created', 'id')
|
|
||||||
ordering_fields = ('created', 'datetime', 'id',)
|
|
||||||
permission = 'can_view_orders'
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
qs = Checkin.all.filter().select_related(
|
|
||||||
"position",
|
|
||||||
"device",
|
|
||||||
)
|
|
||||||
return qs
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
|
||||||
ctx = super().get_serializer_context()
|
|
||||||
ctx['event'] = self.request.event
|
|
||||||
return ctx
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -40,19 +40,19 @@ from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
|||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.exceptions import PermissionDenied, ValidationError
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from pretix.api.pagination import TotalOrderingFilter
|
from pretix.api.pagination import TotalOrderingFilter
|
||||||
from pretix.api.serializers.item import (
|
from pretix.api.serializers.item import (
|
||||||
ItemAddOnSerializer, ItemBundleSerializer, ItemCategorySerializer,
|
ItemAddOnSerializer, ItemBundleSerializer, ItemCategorySerializer,
|
||||||
ItemProgramTimeSerializer, ItemSerializer, ItemVariationSerializer,
|
ItemSerializer, ItemVariationSerializer, QuestionOptionSerializer,
|
||||||
QuestionOptionSerializer, QuestionSerializer, QuotaSerializer,
|
QuestionSerializer, QuotaSerializer,
|
||||||
)
|
)
|
||||||
from pretix.api.views import ConditionalListView
|
from pretix.api.views import ConditionalListView
|
||||||
from pretix.base.models import (
|
from pretix.base.models import (
|
||||||
CartPosition, Item, ItemAddOn, ItemBundle, ItemCategory, ItemProgramTime,
|
CartPosition, Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation,
|
||||||
ItemVariation, Question, QuestionOption, Quota,
|
Question, QuestionOption, Quota,
|
||||||
)
|
)
|
||||||
from pretix.base.services.quotas import QuotaAvailability
|
from pretix.base.services.quotas import QuotaAvailability
|
||||||
from pretix.helpers.dicts import merge_dicts
|
from pretix.helpers.dicts import merge_dicts
|
||||||
@@ -279,59 +279,6 @@ class ItemBundleViewSet(viewsets.ModelViewSet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ItemProgramTimeViewSet(viewsets.ModelViewSet):
|
|
||||||
serializer_class = ItemProgramTimeSerializer
|
|
||||||
queryset = ItemProgramTime.objects.none()
|
|
||||||
filter_backends = (DjangoFilterBackend, TotalOrderingFilter,)
|
|
||||||
ordering_fields = ('id',)
|
|
||||||
ordering = ('id',)
|
|
||||||
permission = None
|
|
||||||
write_permission = 'can_change_items'
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def item(self):
|
|
||||||
return get_object_or_404(Item, pk=self.kwargs['item'], event=self.request.event)
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if self.request.event.has_subevents:
|
|
||||||
raise ValidationError('You cannot use program times on an event series.')
|
|
||||||
return self.item.program_times.all()
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
|
||||||
ctx = super().get_serializer_context()
|
|
||||||
ctx['event'] = self.request.event
|
|
||||||
ctx['item'] = self.item
|
|
||||||
return ctx
|
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
|
||||||
item = get_object_or_404(Item, pk=self.kwargs['item'], event=self.request.event)
|
|
||||||
serializer.save(item=item)
|
|
||||||
item.log_action(
|
|
||||||
'pretix.event.item.program_times.added',
|
|
||||||
user=self.request.user,
|
|
||||||
auth=self.request.auth,
|
|
||||||
data=merge_dicts(self.request.data, {'id': serializer.instance.pk})
|
|
||||||
)
|
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
|
||||||
serializer.save(event=self.request.event)
|
|
||||||
serializer.instance.item.log_action(
|
|
||||||
'pretix.event.item.program_times.changed',
|
|
||||||
user=self.request.user,
|
|
||||||
auth=self.request.auth,
|
|
||||||
data=merge_dicts(self.request.data, {'id': serializer.instance.pk})
|
|
||||||
)
|
|
||||||
|
|
||||||
def perform_destroy(self, instance):
|
|
||||||
super().perform_destroy(instance)
|
|
||||||
instance.item.log_action(
|
|
||||||
'pretix.event.item.program_times.removed',
|
|
||||||
user=self.request.user,
|
|
||||||
auth=self.request.auth,
|
|
||||||
data={'start': instance.start, 'end': instance.end}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ItemAddOnViewSet(viewsets.ModelViewSet):
|
class ItemAddOnViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = ItemAddOnSerializer
|
serializer_class = ItemAddOnSerializer
|
||||||
queryset = ItemAddOn.objects.none()
|
queryset = ItemAddOn.objects.none()
|
||||||
@@ -567,7 +514,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet):
|
|||||||
write_permission = 'can_change_items'
|
write_permission = 'can_change_items'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.request.event.quotas.select_related('subevent').prefetch_related('items', 'variations').all()
|
return self.request.event.quotas.all()
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset()).distinct()
|
queryset = self.filter_queryset(self.get_queryset()).distinct()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -88,7 +88,7 @@ from pretix.base.secrets import assign_ticket_secret
|
|||||||
from pretix.base.services import tickets
|
from pretix.base.services import tickets
|
||||||
from pretix.base.services.invoices import (
|
from pretix.base.services.invoices import (
|
||||||
generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified,
|
generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified,
|
||||||
regenerate_invoice, transmit_invoice,
|
regenerate_invoice,
|
||||||
)
|
)
|
||||||
from pretix.base.services.mail import SendMailException
|
from pretix.base.services.mail import SendMailException
|
||||||
from pretix.base.services.orders import (
|
from pretix.base.services.orders import (
|
||||||
@@ -344,7 +344,6 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
|||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
ctx = super().get_serializer_context()
|
ctx = super().get_serializer_context()
|
||||||
ctx['event'] = self.request.event
|
ctx['event'] = self.request.event
|
||||||
ctx['auth'] = self.request.auth
|
|
||||||
ctx['pdf_data'] = self.request.query_params.get('pdf_data', 'false').lower() == 'true'
|
ctx['pdf_data'] = self.request.query_params.get('pdf_data', 'false').lower() == 'true'
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
@@ -744,7 +743,7 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
|||||||
user=request.user if request.user.is_authenticated else None,
|
user=request.user if request.user.is_authenticated else None,
|
||||||
auth=request.auth,
|
auth=request.auth,
|
||||||
)
|
)
|
||||||
order_placed.send(self.request.event, order=order, bulk=False)
|
order_placed.send(self.request.event, order=order)
|
||||||
if order.status == Order.STATUS_PAID:
|
if order.status == Order.STATUS_PAID:
|
||||||
order_paid.send(self.request.event, order=order)
|
order_paid.send(self.request.event, order=order)
|
||||||
order.log_action(
|
order.log_action(
|
||||||
@@ -765,13 +764,7 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
|||||||
) and not order.invoices.last()
|
) and not order.invoices.last()
|
||||||
invoice = None
|
invoice = None
|
||||||
if gen_invoice:
|
if gen_invoice:
|
||||||
try:
|
|
||||||
invoice = generate_invoice(order, trigger_pdf=True)
|
invoice = generate_invoice(order, trigger_pdf=True)
|
||||||
except Exception as e:
|
|
||||||
logger.exception("Could not generate invoice.")
|
|
||||||
order.log_action("pretix.event.order.invoice.failed", data={
|
|
||||||
"exception": str(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
# Refresh serializer only after running signals
|
# Refresh serializer only after running signals
|
||||||
prefetch_related_objects([order], self._positions_prefetch(request))
|
prefetch_related_objects([order], self._positions_prefetch(request))
|
||||||
@@ -1670,9 +1663,6 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
|||||||
else:
|
else:
|
||||||
mark_refunded = request.data.get('mark_canceled', False)
|
mark_refunded = request.data.get('mark_canceled', False)
|
||||||
|
|
||||||
if not isinstance(request.data.get("comment", ""), str):
|
|
||||||
return Response({'comment': 'Invalid type.'}, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
if payment.state != OrderPayment.PAYMENT_STATE_CONFIRMED:
|
if payment.state != OrderPayment.PAYMENT_STATE_CONFIRMED:
|
||||||
return Response({'detail': 'Invalid state of payment.'}, status=status.HTTP_400_BAD_REQUEST)
|
return Response({'detail': 'Invalid state of payment.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@@ -1699,7 +1689,6 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
|||||||
amount=amount,
|
amount=amount,
|
||||||
provider=payment.provider,
|
provider=payment.provider,
|
||||||
info='{}',
|
info='{}',
|
||||||
comment=request.data.get("comment"),
|
|
||||||
)
|
)
|
||||||
payment.order.log_action('pretix.event.order.refund.created', {
|
payment.order.log_action('pretix.event.order.refund.created', {
|
||||||
'local_id': r.local_id,
|
'local_id': r.local_id,
|
||||||
@@ -1902,12 +1891,6 @@ class RetryException(APIException):
|
|||||||
default_code = 'retry_later'
|
default_code = 'retry_later'
|
||||||
|
|
||||||
|
|
||||||
class CurrentlyInflightException(APIException):
|
|
||||||
status_code = 409
|
|
||||||
default_detail = 'The requested action is already in progress.'
|
|
||||||
default_code = 'currently_inflight'
|
|
||||||
|
|
||||||
|
|
||||||
class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
serializer_class = InvoiceSerializer
|
serializer_class = InvoiceSerializer
|
||||||
queryset = Invoice.objects.none()
|
queryset = Invoice.objects.none()
|
||||||
@@ -1956,52 +1939,13 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
|||||||
resp['Content-Disposition'] = 'attachment; filename="{}.pdf"'.format(invoice.number)
|
resp['Content-Disposition'] = 'attachment; filename="{}.pdf"'.format(invoice.number)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@action(detail=True, methods=['POST'])
|
|
||||||
def transmit(self, request, **kwargs):
|
|
||||||
invoice = self.get_object()
|
|
||||||
if invoice.shredded:
|
|
||||||
raise PermissionDenied('The invoice file is no longer stored on the server.')
|
|
||||||
|
|
||||||
if invoice.transmission_status != Invoice.TRANSMISSION_STATUS_PENDING:
|
|
||||||
raise PermissionDenied('The invoice is not in pending state.')
|
|
||||||
|
|
||||||
transmit_invoice.apply_async(args=(self.request.event.pk, invoice.pk, False))
|
|
||||||
return Response(status=204)
|
|
||||||
|
|
||||||
@action(detail=True, methods=['POST'])
|
|
||||||
def retransmit(self, request, **kwargs):
|
|
||||||
invoice = self.get_object()
|
|
||||||
if invoice.shredded:
|
|
||||||
raise PermissionDenied('The invoice file is no longer stored on the server.')
|
|
||||||
|
|
||||||
with transaction.atomic(durable=True):
|
|
||||||
invoice = Invoice.objects.select_for_update(of=OF_SELF).get(pk=invoice.pk)
|
|
||||||
|
|
||||||
if invoice.transmission_status == Invoice.TRANSMISSION_STATUS_INFLIGHT:
|
|
||||||
raise CurrentlyInflightException()
|
|
||||||
|
|
||||||
invoice.transmission_status = Invoice.TRANSMISSION_STATUS_PENDING
|
|
||||||
invoice.transmission_date = now()
|
|
||||||
invoice.save(update_fields=["transmission_status", "transmission_date"])
|
|
||||||
invoice.order.log_action(
|
|
||||||
'pretix.event.order.invoice.retransmitted',
|
|
||||||
user=self.request.user,
|
|
||||||
auth=self.request.auth,
|
|
||||||
data={
|
|
||||||
'invoice': invoice.pk,
|
|
||||||
'full_invoice_no': invoice.full_invoice_no,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
transmit_invoice.apply_async(args=(self.request.event.pk, invoice.pk, True))
|
|
||||||
return Response(status=204)
|
|
||||||
|
|
||||||
@action(detail=True, methods=['POST'])
|
@action(detail=True, methods=['POST'])
|
||||||
def regenerate(self, request, **kwargs):
|
def regenerate(self, request, **kwargs):
|
||||||
inv = self.get_object()
|
inv = self.get_object()
|
||||||
if inv.canceled:
|
if inv.canceled:
|
||||||
raise ValidationError('The invoice has already been canceled.')
|
raise ValidationError('The invoice has already been canceled.')
|
||||||
if not inv.regenerate_allowed:
|
if not inv.event.settings.invoice_regenerate_allowed:
|
||||||
raise PermissionDenied('Invoice may not be regenerated.')
|
raise PermissionDenied('Invoices may not be changed after they are created.')
|
||||||
elif inv.shredded:
|
elif inv.shredded:
|
||||||
raise PermissionDenied('The invoice file is no longer stored on the server.')
|
raise PermissionDenied('The invoice file is no longer stored on the server.')
|
||||||
elif inv.sent_to_organizer:
|
elif inv.sent_to_organizer:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -546,8 +546,7 @@ class DeviceViewSet(mixins.CreateModelMixin,
|
|||||||
|
|
||||||
|
|
||||||
class OrganizerSettingsView(views.APIView):
|
class OrganizerSettingsView(views.APIView):
|
||||||
permission = None
|
permission = 'can_change_organizer_settings'
|
||||||
write_permission = 'can_change_organizer_settings'
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
||||||
@@ -721,7 +720,7 @@ class MembershipViewSet(viewsets.ModelViewSet):
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Membership.objects.filter(
|
return Membership.objects.filter(
|
||||||
customer__organizer=self.request.organizer
|
customer__organizer=self.request.organizer
|
||||||
).select_related('customer')
|
)
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
ctx = super().get_serializer_context()
|
ctx = super().get_serializer_context()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
@@ -65,13 +64,8 @@ class VoucherViewSet(viewsets.ModelViewSet):
|
|||||||
permission = 'can_view_vouchers'
|
permission = 'can_view_vouchers'
|
||||||
write_permission = 'can_change_vouchers'
|
write_permission = 'can_change_vouchers'
|
||||||
|
|
||||||
@scopes_disabled() # we have an event check here, and we can save some performance on subqueries
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Voucher.annotate_budget_used(
|
return self.request.event.vouchers.select_related('seat').all()
|
||||||
self.request.event.vouchers
|
|
||||||
).select_related(
|
|
||||||
'item', 'quota', 'seat', 'variation'
|
|
||||||
)
|
|
||||||
|
|
||||||
@transaction.atomic()
|
@transaction.atomic()
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -43,7 +43,6 @@ from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask
|
|||||||
from pretix.base.signals import periodic_task
|
from pretix.base.signals import periodic_task
|
||||||
from pretix.celery_app import app
|
from pretix.celery_app import app
|
||||||
from pretix.helpers import OF_SELF
|
from pretix.helpers import OF_SELF
|
||||||
from pretix.helpers.celery import get_task_priority
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
_ALL_EVENTS = None
|
_ALL_EVENTS = None
|
||||||
@@ -79,13 +78,6 @@ class WebhookEvent:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError() # NOQA
|
raise NotImplementedError() # NOQA
|
||||||
|
|
||||||
@property
|
|
||||||
def help_text(self) -> str:
|
|
||||||
"""
|
|
||||||
A human-readable description
|
|
||||||
"""
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def get_all_webhook_events():
|
def get_all_webhook_events():
|
||||||
global _ALL_EVENTS
|
global _ALL_EVENTS
|
||||||
@@ -105,10 +97,9 @@ def get_all_webhook_events():
|
|||||||
|
|
||||||
|
|
||||||
class ParametrizedWebhookEvent(WebhookEvent):
|
class ParametrizedWebhookEvent(WebhookEvent):
|
||||||
def __init__(self, action_type, verbose_name, help_text=""):
|
def __init__(self, action_type, verbose_name):
|
||||||
self._action_type = action_type
|
self._action_type = action_type
|
||||||
self._verbose_name = verbose_name
|
self._verbose_name = verbose_name
|
||||||
self._help_text = help_text
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -119,10 +110,6 @@ class ParametrizedWebhookEvent(WebhookEvent):
|
|||||||
def verbose_name(self):
|
def verbose_name(self):
|
||||||
return self._verbose_name
|
return self._verbose_name
|
||||||
|
|
||||||
@property
|
|
||||||
def help_text(self):
|
|
||||||
return self._help_text
|
|
||||||
|
|
||||||
|
|
||||||
class ParametrizedOrderWebhookEvent(ParametrizedWebhookEvent):
|
class ParametrizedOrderWebhookEvent(ParametrizedWebhookEvent):
|
||||||
def build_payload(self, logentry: LogEntry):
|
def build_payload(self, logentry: LogEntry):
|
||||||
@@ -174,19 +161,6 @@ class ParametrizedEventWebhookEvent(ParametrizedWebhookEvent):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ParametrizedVoucherWebhookEvent(ParametrizedWebhookEvent):
|
|
||||||
|
|
||||||
def build_payload(self, logentry: LogEntry):
|
|
||||||
# do not use content_object, this is also called in deletion
|
|
||||||
return {
|
|
||||||
'notification_id': logentry.pk,
|
|
||||||
'organizer': logentry.event.organizer.slug,
|
|
||||||
'event': logentry.event.slug,
|
|
||||||
'voucher': logentry.object_id,
|
|
||||||
'action': logentry.action_type,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ParametrizedSubEventWebhookEvent(ParametrizedWebhookEvent):
|
class ParametrizedSubEventWebhookEvent(ParametrizedWebhookEvent):
|
||||||
|
|
||||||
def build_payload(self, logentry: LogEntry):
|
def build_payload(self, logentry: LogEntry):
|
||||||
@@ -372,9 +346,8 @@ def register_default_webhook_events(sender, **kwargs):
|
|||||||
),
|
),
|
||||||
ParametrizedItemWebhookEvent(
|
ParametrizedItemWebhookEvent(
|
||||||
'pretix.event.item.*',
|
'pretix.event.item.*',
|
||||||
_('Product changed'),
|
_('Product changed (including product added or deleted and including changes to nested objects like '
|
||||||
_('This includes product added or deleted and changes to nested objects like '
|
'variations or bundles)'),
|
||||||
'variations or bundles.'),
|
|
||||||
),
|
),
|
||||||
ParametrizedEventWebhookEvent(
|
ParametrizedEventWebhookEvent(
|
||||||
'pretix.event.live.activated',
|
'pretix.event.live.activated',
|
||||||
@@ -408,19 +381,6 @@ def register_default_webhook_events(sender, **kwargs):
|
|||||||
'pretix.event.orders.waitinglist.voucher_assigned',
|
'pretix.event.orders.waitinglist.voucher_assigned',
|
||||||
_('Waiting list entry received voucher'),
|
_('Waiting list entry received voucher'),
|
||||||
),
|
),
|
||||||
ParametrizedVoucherWebhookEvent(
|
|
||||||
'pretix.voucher.added',
|
|
||||||
_('Voucher added'),
|
|
||||||
),
|
|
||||||
ParametrizedVoucherWebhookEvent(
|
|
||||||
'pretix.voucher.changed',
|
|
||||||
_('Voucher changed'),
|
|
||||||
_('Only includes explicit changes to the voucher, not e.g. an increase of the number of redemptions.')
|
|
||||||
),
|
|
||||||
ParametrizedVoucherWebhookEvent(
|
|
||||||
'pretix.voucher.deleted',
|
|
||||||
_('Voucher deleted'),
|
|
||||||
),
|
|
||||||
ParametrizedCustomerWebhookEvent(
|
ParametrizedCustomerWebhookEvent(
|
||||||
'pretix.customer.created',
|
'pretix.customer.created',
|
||||||
_('Customer account created'),
|
_('Customer account created'),
|
||||||
@@ -440,12 +400,8 @@ def register_default_webhook_events(sender, **kwargs):
|
|||||||
def notify_webhooks(logentry_ids: list):
|
def notify_webhooks(logentry_ids: list):
|
||||||
if not isinstance(logentry_ids, list):
|
if not isinstance(logentry_ids, list):
|
||||||
logentry_ids = [logentry_ids]
|
logentry_ids = [logentry_ids]
|
||||||
qs = LogEntry.all.select_related(
|
qs = LogEntry.all.select_related('event', 'event__organizer', 'organizer').filter(id__in=logentry_ids)
|
||||||
'event', 'event__organizer', 'organizer'
|
_org, _at, webhooks = None, None, None
|
||||||
).order_by(
|
|
||||||
'action_type', 'organizer_id', 'event_id',
|
|
||||||
).filter(id__in=logentry_ids)
|
|
||||||
_org, _at, _ev, webhooks = None, None, None, None
|
|
||||||
for logentry in qs:
|
for logentry in qs:
|
||||||
if not logentry.organizer:
|
if not logentry.organizer:
|
||||||
break # We need to know the organizer
|
break # We need to know the organizer
|
||||||
@@ -455,7 +411,7 @@ def notify_webhooks(logentry_ids: list):
|
|||||||
if not notification_type:
|
if not notification_type:
|
||||||
break # Ignore, no webhooks for this event type
|
break # Ignore, no webhooks for this event type
|
||||||
|
|
||||||
if _org != logentry.organizer or _at != logentry.action_type or _ev != logentry.event_id or webhooks is None:
|
if _org != logentry.organizer or _at != logentry.action_type or webhooks is None:
|
||||||
_org = logentry.organizer
|
_org = logentry.organizer
|
||||||
_at = logentry.action_type
|
_at = logentry.action_type
|
||||||
|
|
||||||
@@ -475,10 +431,7 @@ def notify_webhooks(logentry_ids: list):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for wh in webhooks:
|
for wh in webhooks:
|
||||||
send_webhook.apply_async(
|
send_webhook.apply_async(args=(logentry.id, notification_type.action_type, wh.pk))
|
||||||
args=(logentry.id, notification_type.action_type, wh.pk),
|
|
||||||
priority=get_task_priority("notifications", logentry.organizer_id),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=60, acks_late=True, autoretry_for=(DatabaseError,),)
|
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=60, acks_late=True, autoretry_for=(DatabaseError,),)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -43,7 +43,7 @@ class PretixBaseConfig(AppConfig):
|
|||||||
from . import exporter # NOQA
|
from . import exporter # NOQA
|
||||||
from . import payment # NOQA
|
from . import payment # NOQA
|
||||||
from . import exporters # NOQA
|
from . import exporters # NOQA
|
||||||
from .invoicing import pdf, transmission, email, peppol, national # NOQA
|
from . import invoice # NOQA
|
||||||
from . import notifications # NOQA
|
from . import notifications # NOQA
|
||||||
from . import email # NOQA
|
from . import email # NOQA
|
||||||
from .services import auth, checkin, currencies, datasync, export, mail, tickets, cart, modelimport, orders, invoices, cleanup, update_check, quotas, notifications, vouchers # NOQA
|
from .services import auth, checkin, currencies, datasync, export, mail, tickets, cart, modelimport, orders, invoices, cleanup, update_check, quotas, notifications, vouchers # NOQA
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -112,6 +112,23 @@ def oidc_validate_and_complete_config(config):
|
|||||||
scope="openid",
|
scope="openid",
|
||||||
))
|
))
|
||||||
|
|
||||||
|
for scope in config["scope"].split(" "):
|
||||||
|
if scope not in provider_config.get("scopes_supported", []):
|
||||||
|
raise ValidationError(_('You are requesting scope "{scope}" but provider only supports these: {scopes}.').format(
|
||||||
|
scope=scope,
|
||||||
|
scopes=", ".join(provider_config.get("scopes_supported", []))
|
||||||
|
))
|
||||||
|
|
||||||
|
if "claims_supported" in provider_config:
|
||||||
|
claims_supported = provider_config.get("claims_supported", [])
|
||||||
|
for k, v in config.items():
|
||||||
|
if k.endswith('_field') and v:
|
||||||
|
if v not in claims_supported: # https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
||||||
|
raise ValidationError(_('You are requesting field "{field}" but provider only supports these: {fields}.').format(
|
||||||
|
field=v,
|
||||||
|
fields=", ".join(provider_config.get("claims_supported", []))
|
||||||
|
))
|
||||||
|
|
||||||
if "token_endpoint_auth_methods_supported" in provider_config:
|
if "token_endpoint_auth_methods_supported" in provider_config:
|
||||||
token_endpoint_auth_methods_supported = provider_config.get("token_endpoint_auth_methods_supported",
|
token_endpoint_auth_methods_supported = provider_config.get("token_endpoint_auth_methods_supported",
|
||||||
["client_secret_basic"])
|
["client_secret_basic"])
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -90,7 +90,6 @@ StaticMapping = namedtuple('StaticMapping', ('id', 'pretix_model', 'external_obj
|
|||||||
|
|
||||||
class OutboundSyncProvider:
|
class OutboundSyncProvider:
|
||||||
max_attempts = 5
|
max_attempts = 5
|
||||||
list_field_joiner = "," # set to None to keep native lists in properties
|
|
||||||
|
|
||||||
def __init__(self, event):
|
def __init__(self, event):
|
||||||
self.event = event
|
self.event = event
|
||||||
@@ -107,7 +106,7 @@ class OutboundSyncProvider:
|
|||||||
return str(cls.identifier)
|
return str(cls.identifier)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def enqueue_order(cls, order, triggered_by, not_before=None, immediate=False):
|
def enqueue_order(cls, order, triggered_by, not_before=None):
|
||||||
"""
|
"""
|
||||||
Adds an order to the sync queue. May only be called on derived classes which define an ``identifier`` attribute.
|
Adds an order to the sync queue. May only be called on derived classes which define an ``identifier`` attribute.
|
||||||
|
|
||||||
@@ -120,14 +119,10 @@ class OutboundSyncProvider:
|
|||||||
:param order: the Order that should be synced
|
:param order: the Order that should be synced
|
||||||
:param triggered_by: the reason why the order should be synced, e.g. name of the signal
|
:param triggered_by: the reason why the order should be synced, e.g. name of the signal
|
||||||
(currently only used internally for logging)
|
(currently only used internally for logging)
|
||||||
:param immediate: whether a new sync task should run immediately for this order, instead
|
|
||||||
of waiting for the next periodic_task interval
|
|
||||||
:return: Return a tuple (queue_item, created), where created is a boolean
|
|
||||||
specifying whether a new queue item was created.
|
|
||||||
"""
|
"""
|
||||||
if not hasattr(cls, 'identifier'):
|
if not hasattr(cls, 'identifier'):
|
||||||
raise TypeError('Call this method on a derived class that defines an "identifier" attribute.')
|
raise TypeError('Call this method on a derived class that defines an "identifier" attribute.')
|
||||||
queue_item, created = OrderSyncQueue.objects.update_or_create(
|
OrderSyncQueue.objects.update_or_create(
|
||||||
order=order,
|
order=order,
|
||||||
sync_provider=cls.identifier,
|
sync_provider=cls.identifier,
|
||||||
in_flight=False,
|
in_flight=False,
|
||||||
@@ -138,10 +133,6 @@ class OutboundSyncProvider:
|
|||||||
"need_manual_retry": None,
|
"need_manual_retry": None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if immediate:
|
|
||||||
from pretix.base.services.datasync import sync_single
|
|
||||||
sync_single.apply_async(args=(queue_item.pk,))
|
|
||||||
return queue_item, created
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_external_link_info(cls, event, external_link_href, external_link_display_name):
|
def get_external_link_info(cls, event, external_link_href, external_link_display_name):
|
||||||
@@ -261,15 +252,9 @@ class OutboundSyncProvider:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
with language(self.event.settings.locale):
|
with language(self.event.settings.locale):
|
||||||
raise SyncConfigError([_(
|
raise SyncConfigError([_(
|
||||||
'Field "{field_name}" does not exist. Please check your {provider_name} settings.'
|
'Field "{field_name}" is not valid for {available_inputs}. Please check your {provider_name} settings.'
|
||||||
).format(field_name=key, provider_name=self.display_name)])
|
).format(key=key, available_inputs="/".join(inputs.keys()), provider_name=self.display_name)])
|
||||||
try:
|
|
||||||
input = inputs[field.required_input]
|
input = inputs[field.required_input]
|
||||||
except KeyError:
|
|
||||||
with language(self.event.settings.locale):
|
|
||||||
raise SyncConfigError([_(
|
|
||||||
'Field "{field_name}" requires {required_input}, but only got {available_inputs}. Please check your {provider_name} settings.'
|
|
||||||
).format(field_name=key, required_input=field.required_input, available_inputs=", ".join(inputs.keys()), provider_name=self.display_name)])
|
|
||||||
val = field.getter(input)
|
val = field.getter(input)
|
||||||
if isinstance(val, list):
|
if isinstance(val, list):
|
||||||
if field.enum_opts and mapping_entry.get("value_map"):
|
if field.enum_opts and mapping_entry.get("value_map"):
|
||||||
@@ -282,8 +267,7 @@ class OutboundSyncProvider:
|
|||||||
'Please update value mapping for field "{field_name}" - option "{val}" not assigned'
|
'Please update value mapping for field "{field_name}" - option "{val}" not assigned'
|
||||||
).format(field_name=key, val=val)])
|
).format(field_name=key, val=val)])
|
||||||
|
|
||||||
if self.list_field_joiner:
|
val = ",".join(val)
|
||||||
val = self.list_field_joiner.join(val)
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def get_properties(self, inputs: dict, property_mappings: List[dict]):
|
def get_properties(self, inputs: dict, property_mappings: List[dict]):
|
||||||
@@ -393,7 +377,7 @@ class OutboundSyncProvider:
|
|||||||
def sync_order(self, order):
|
def sync_order(self, order):
|
||||||
if not self.should_sync_order(order):
|
if not self.should_sync_order(order):
|
||||||
logger.debug("Skipping order %r", order)
|
logger.debug("Skipping order %r", order)
|
||||||
return {}
|
return
|
||||||
|
|
||||||
logger.debug("Syncing order %r", order)
|
logger.debug("Syncing order %r", order)
|
||||||
positions = list(
|
positions = list(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -24,7 +24,7 @@ from collections import namedtuple
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from django.db.models import Max, Q
|
from django.db.models import Max, Q
|
||||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from pretix.base.models import Checkin, InvoiceAddress, Order, Question
|
from pretix.base.models import Checkin, InvoiceAddress, Order, Question
|
||||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||||
@@ -132,7 +132,7 @@ CAT_PRODUCT = DataFieldCategory(20, _('Product details'))
|
|||||||
CAT_ORDER = DataFieldCategory(21, _('Order details'))
|
CAT_ORDER = DataFieldCategory(21, _('Order details'))
|
||||||
CAT_INVOICE_ADDRESS = DataFieldCategory(22, _('Invoice address'))
|
CAT_INVOICE_ADDRESS = DataFieldCategory(22, _('Invoice address'))
|
||||||
CAT_EVENT = DataFieldCategory(30, _('Event information'))
|
CAT_EVENT = DataFieldCategory(30, _('Event information'))
|
||||||
CAT_EVENT_OR_SUBEVENT = DataFieldCategory(31, pgettext_lazy('subevent', 'Event or date information'))
|
CAT_EVENT_OR_SUBEVENT = DataFieldCategory(31, _('Event or subevent information'))
|
||||||
|
|
||||||
DataFieldInfo = namedtuple(
|
DataFieldInfo = namedtuple(
|
||||||
'DataFieldInfo',
|
'DataFieldInfo',
|
||||||
@@ -524,7 +524,7 @@ def get_data_fields(event, for_model=None):
|
|||||||
ORDER,
|
ORDER,
|
||||||
CAT_ORDER,
|
CAT_ORDER,
|
||||||
"order_locale",
|
"order_locale",
|
||||||
_("Order locale"),
|
_("Order language code"),
|
||||||
Question.TYPE_CHOICE,
|
Question.TYPE_CHOICE,
|
||||||
[(lc, lc) for lc in event.settings.locales],
|
[(lc, lc) for lc in event.settings.locales],
|
||||||
lambda order: [order.locale],
|
lambda order: [order.locale],
|
||||||
@@ -542,7 +542,7 @@ def get_data_fields(event, for_model=None):
|
|||||||
ORDER,
|
ORDER,
|
||||||
CAT_ORDER,
|
CAT_ORDER,
|
||||||
"presale_order_url",
|
"presale_order_url",
|
||||||
_("Order link"),
|
_("Order URL"),
|
||||||
Question.TYPE_STRING,
|
Question.TYPE_STRING,
|
||||||
None,
|
None,
|
||||||
lambda order: build_absolute_uri(
|
lambda order: build_absolute_uri(
|
||||||
@@ -557,7 +557,7 @@ def get_data_fields(event, for_model=None):
|
|||||||
ORDER_POSITION,
|
ORDER_POSITION,
|
||||||
CAT_ORDER_POSITION,
|
CAT_ORDER_POSITION,
|
||||||
"presale_ticket_url",
|
"presale_ticket_url",
|
||||||
_("Ticket link"),
|
_("Ticket URL"),
|
||||||
Question.TYPE_STRING,
|
Question.TYPE_STRING,
|
||||||
None,
|
None,
|
||||||
lambda op: build_absolute_uri(
|
lambda op: build_absolute_uri(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -71,20 +71,15 @@ def assign_properties(
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def _add_to_list(out, field_name, current_value, new_item_input, list_sep):
|
def _add_to_list(out, field_name, current_value, new_item, list_sep):
|
||||||
|
new_item = str(new_item)
|
||||||
if list_sep is not None:
|
if list_sep is not None:
|
||||||
new_items = str(new_item_input).split(list_sep)
|
new_item = new_item.replace(list_sep, "")
|
||||||
current_value = current_value.split(list_sep) if current_value else []
|
current_value = current_value.split(list_sep) if current_value else []
|
||||||
else:
|
elif not isinstance(current_value, (list, tuple)):
|
||||||
new_items = [str(new_item_input)]
|
|
||||||
if not isinstance(current_value, (list, tuple)):
|
|
||||||
current_value = [str(current_value)]
|
current_value = [str(current_value)]
|
||||||
|
|
||||||
new_list = list(current_value)
|
|
||||||
for new_item in new_items:
|
|
||||||
if new_item not in current_value:
|
if new_item not in current_value:
|
||||||
new_list.append(new_item)
|
new_list = current_value + [new_item]
|
||||||
if new_list != current_value:
|
|
||||||
if list_sep is not None:
|
if list_sep is not None:
|
||||||
new_list = list_sep.join(new_list)
|
new_list = list_sep.join(new_list)
|
||||||
out[field_name] = new_list
|
out[field_name] = new_list
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -24,7 +24,6 @@ from itertools import groupby
|
|||||||
from smtplib import SMTPResponseException
|
from smtplib import SMTPResponseException
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
import bleach
|
|
||||||
import css_inline
|
import css_inline
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail.backends.smtp import EmailBackend
|
from django.core.mail.backends.smtp import EmailBackend
|
||||||
@@ -35,10 +34,7 @@ from django.utils.translation import get_language, gettext_lazy as _
|
|||||||
|
|
||||||
from pretix.base.models import Event
|
from pretix.base.models import Event
|
||||||
from pretix.base.signals import register_html_mail_renderers
|
from pretix.base.signals import register_html_mail_renderers
|
||||||
from pretix.base.templatetags.rich_text import (
|
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||||
DEFAULT_CALLBACKS, EMAIL_RE, URL_RE, abslink_callback,
|
|
||||||
markdown_compile_email, truelink_callback,
|
|
||||||
)
|
|
||||||
from pretix.helpers.format import SafeFormatter, format_map
|
from pretix.helpers.format import SafeFormatter, format_map
|
||||||
|
|
||||||
from pretix.base.services.placeholders import ( # noqa
|
from pretix.base.services.placeholders import ( # noqa
|
||||||
@@ -137,24 +133,13 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
|
|||||||
def template_name(self):
|
def template_name(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def compile_markdown(self, plaintext, context=None):
|
def compile_markdown(self, plaintext):
|
||||||
return markdown_compile_email(plaintext, context=context)
|
return markdown_compile_email(plaintext)
|
||||||
|
|
||||||
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
|
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
|
||||||
body_md = self.compile_markdown(plain_body, context)
|
body_md = self.compile_markdown(plain_body)
|
||||||
if context:
|
if context:
|
||||||
linker = bleach.Linker(
|
body_md = format_map(body_md, context=context, mode=SafeFormatter.MODE_RICH_TO_HTML)
|
||||||
url_re=URL_RE,
|
|
||||||
email_re=EMAIL_RE,
|
|
||||||
callbacks=DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
|
|
||||||
parse_email=True
|
|
||||||
)
|
|
||||||
body_md = format_map(
|
|
||||||
body_md,
|
|
||||||
context=context,
|
|
||||||
mode=SafeFormatter.MODE_RICH_TO_HTML,
|
|
||||||
linkifier=linker
|
|
||||||
)
|
|
||||||
htmlctx = {
|
htmlctx = {
|
||||||
'site': settings.PRETIX_INSTANCE_NAME,
|
'site': settings.PRETIX_INSTANCE_NAME,
|
||||||
'site_url': settings.SITE_URL,
|
'site_url': settings.SITE_URL,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
@@ -105,18 +105,6 @@ class BaseExporter:
|
|||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
def repeatable_read(self) -> bool:
|
|
||||||
"""
|
|
||||||
If ``True``, this exporter will be run in a REPEATABLE READ transaction. This ensures consistent results for
|
|
||||||
all queries performed by the exporter, but creates a performance burden on the database server. We recommend to
|
|
||||||
disable this for exporters that take very long to run and do not rely on this behavior, such as export of lists
|
|
||||||
to CSV files.
|
|
||||||
|
|
||||||
Defaults to ``True`` for now, but default may change in future versions.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def identifier(self) -> str:
|
def identifier(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is part of pretix (Community Edition).
|
# This file is part of pretix (Community Edition).
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user