Compare commits

..

15 Commits

Author SHA1 Message Date
Mira Weller
840cc6edda Fix log entry details for datasync logs without external link (Z#23210015) 2025-10-07 13:41:35 +02:00
Martin Gross
22f351cb89 OCM: Ignore already canceled addons in remaining item calculation (Z#23209824) 2025-10-02 10:30:33 +02:00
Raphael Michel
2611ff74a5 Badges: Fix incorrect offsets for DURABLE 8334-02 2025-10-02 09:57:59 +02:00
Hijiri Umemoto
cc1c7e1c23 Translations: Update Japanese
Currently translated at 100.0% (6076 of 6076 strings)

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

powered by weblate
2025-10-02 09:50:39 +02:00
CVZ-es
e2eedac93b Translations: Update Spanish
Currently translated at 100.0% (6076 of 6076 strings)

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

powered by weblate
2025-10-02 09:50:39 +02:00
CVZ-es
432064c3ae Translations: Update French
Currently translated at 100.0% (6076 of 6076 strings)

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

powered by weblate
2025-10-02 09:50:39 +02:00
Raphael Michel
457115f4ca Add refund comment to gift card transaction text (Z#23208349) (#5499)
* Add refund comment to gift card transaction text (Z#23208349)

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

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

---------

Co-authored-by: luelista <weller@rami.io>
2025-10-02 09:38:32 +02:00
luelista
9d5563018e Add "bulk" argument to order_placed signal (#5505)
* datasync: add immediate parameter to enqueue_order

* interactive argument for order_placed signal

The ``interactive`` argument specifies whether the order was
placed interactively, by a customer (as opposed to via a bulk
import or the REST API).

* use bulk=True instead of interactive=False to mark bulk imports
2025-10-02 09:36:02 +02:00
luelista
425f4da1f1 datasync: add immediate parameter to enqueue_order (#5504) 2025-10-02 09:34:56 +02:00
dependabot[bot]
aa0ea27d6c Update isort requirement from ==6.0.* to ==6.1.* (#5507) 2025-10-02 09:32:10 +02:00
dependabot[bot]
5a2219124a Bump @babel/core from 7.28.3 to 7.28.4 in /src/pretix/static/npm_dir (#5506)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.28.3 to 7.28.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-core)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 09:32:02 +02:00
luelista
f79813ea32 datasync: return a reference to newly create queue item (#5502) 2025-09-30 17:25:25 +02:00
luelista
ba62db7a19 Fix version number (2024 -> 2025) 2025-09-30 16:01:27 +02:00
Jan Van Haver
aa8b699b89 Translations: Update Dutch
Currently translated at 96.9% (5892 of 6076 strings)

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

powered by weblate
2025-09-30 09:19:26 +02:00
dependabot[bot]
6adabd54dc Update beautifulsoup4 requirement from ==4.13.* to ==4.14.*
Updates the requirements on [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/) to permit the latest version.

---
updated-dependencies:
- dependency-name: beautifulsoup4
  dependency-version: 4.14.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 09:19:21 +02:00
29 changed files with 245 additions and 427 deletions

View File

@@ -28,14 +28,14 @@ classifiers = [
dependencies = [
"arabic-reshaper==3.0.0", # Support for Arabic in reportlab
"babel",
"BeautifulSoup4==4.13.*",
"BeautifulSoup4==4.14.*",
"bleach==6.2.*",
"celery==5.5.*",
"chardet==5.2.*",
"cryptography>=44.0.0",
"css-inline==0.17.*",
"defusedcsv>=1.1.0",
"Django[argon2]==4.2.*,>=4.2.25",
"Django[argon2]==4.2.*,>=4.2.24",
"django-bootstrap3==25.2",
"django-compressor==4.5.1",
"django-countries==7.6.*",
@@ -113,7 +113,7 @@ dev = [
"fakeredis==2.31.*",
"flake8==7.3.*",
"freezegun",
"isort==6.0.*",
"isort==6.1.*",
"pep8-naming==0.15.*",
"potypo",
"pytest-asyncio>=0.24",

View File

@@ -19,4 +19,4 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
__version__ = "2024.9.0.dev0"
__version__ = "2025.9.0.dev0"

View File

@@ -743,7 +743,7 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
user=request.user if request.user.is_authenticated else None,
auth=request.auth,
)
order_placed.send(self.request.event, order=order)
order_placed.send(self.request.event, order=order, bulk=False)
if order.status == Order.STATUS_PAID:
order_paid.send(self.request.event, order=order)
order.log_action(

View File

@@ -106,7 +106,7 @@ class OutboundSyncProvider:
return str(cls.identifier)
@classmethod
def enqueue_order(cls, order, triggered_by, not_before=None):
def enqueue_order(cls, order, triggered_by, not_before=None, immediate=False):
"""
Adds an order to the sync queue. May only be called on derived classes which define an ``identifier`` attribute.
@@ -119,10 +119,14 @@ class OutboundSyncProvider:
: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
(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'):
raise TypeError('Call this method on a derived class that defines an "identifier" attribute.')
OrderSyncQueue.objects.update_or_create(
queue_item, created = OrderSyncQueue.objects.update_or_create(
order=order,
sync_provider=cls.identifier,
in_flight=False,
@@ -133,6 +137,10 @@ class OutboundSyncProvider:
"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
def get_external_link_info(cls, event, external_link_href, external_link_display_name):

View File

@@ -105,18 +105,6 @@ class BaseExporter:
"""
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
def identifier(self) -> str:
"""

View File

@@ -180,7 +180,6 @@ class InvoiceDataExporter(InvoiceExporterMixin, MultiSheetListExporter):
'includes two sheets, one with a line for every invoice, and one with a line for every position of '
'every invoice.')
featured = True
repeatable_read = False
@property
def additional_form_fields(self):

View File

@@ -90,7 +90,6 @@ class OrderListExporter(MultiSheetListExporter):
'with a line for every order, one with a line for every order position, and one with '
'a line for every additional fee charged in an order.')
featured = True
repeatable_read = False
@cached_property
def providers(self):
@@ -843,7 +842,6 @@ class TransactionListExporter(ListExporter):
description = gettext_lazy('Download a spreadsheet of all substantial changes to orders, i.e. all changes to '
'products, prices or tax rates. The information is only accurate for changes made with '
'pretix versions released after October 2021.')
repeatable_read = False
@cached_property
def providers(self):
@@ -1022,7 +1020,6 @@ class PaymentListExporter(ListExporter):
category = pgettext_lazy('export_category', 'Order data')
description = gettext_lazy('Download a spreadsheet of all payments or refunds of every order.')
featured = True
repeatable_read = False
@property
def additional_form_fields(self):
@@ -1162,7 +1159,7 @@ class QuotaListExporter(ListExporter):
yield headers
quotas = list(self.event.quotas.select_related('subevent'))
qa = QuotaAvailability(full_results=True, allow_repeatable_read=False)
qa = QuotaAvailability(full_results=True)
qa.queue(*quotas)
qa.compute()
@@ -1203,7 +1200,6 @@ class GiftcardTransactionListExporter(OrganizerLevelExportMixin, ListExporter):
organizer_required_permission = 'can_manage_gift_cards'
category = pgettext_lazy('export_category', 'Gift cards')
description = gettext_lazy('Download a spreadsheet of all gift card transactions.')
repeatable_read = False
@property
def additional_form_fields(self):
@@ -1262,7 +1258,6 @@ class GiftcardRedemptionListExporter(ListExporter):
verbose_name = gettext_lazy('Gift card redemptions')
category = pgettext_lazy('export_category', 'Order data')
description = gettext_lazy('Download a spreadsheet of all payments or refunds that involve gift cards.')
repeatable_read = False
def iterate_list(self, form_data):
payments = OrderPayment.objects.filter(

View File

@@ -34,7 +34,6 @@ class ReusableMediaExporter(OrganizerLevelExportMixin, ListExporter):
verbose_name = _('Reusable media')
category = pgettext_lazy('export_category', 'Reusable media')
description = _('Download a spread sheet with the data of all reusable medias on your account.')
repeatable_read = False
def iterate_list(self, form_data):
media = ReusableMedium.objects.filter(

View File

@@ -41,7 +41,6 @@ class WaitingListExporter(ListExporter):
verbose_name = _('Waiting list')
category = pgettext_lazy('export_category', 'Waiting list')
description = _('Download a spread sheet with all your waiting list data.')
repeatable_read = False
# map selected status to label and queryset-filter
status_filters = [

View File

@@ -195,20 +195,21 @@ class GiftCardTransaction(models.Model):
return response
if self.order_id:
if not self.text:
if not customer_facing:
return format_html(
'<a href="{}">{}</a>',
reverse(
"control:event.order",
kwargs={
"event": self.order.event.slug,
"organizer": self.order.event.organizer.slug,
"code": self.order.code,
}
),
self.order.full_code
)
if not customer_facing:
return format_html(
'<a href="{}">{}</a> {}',
reverse(
"control:event.order",
kwargs={
"event": self.order.event.slug,
"organizer": self.order.event.organizer.slug,
"code": self.order.code,
}
),
self.order.full_code,
self.text or "",
)
elif not self.text:
return self.order.full_code
else:
return self.text

View File

@@ -1627,6 +1627,7 @@ class GiftCardPayment(BasePaymentProvider):
order=refund.order,
refund=refund,
acceptor=self.event.organizer,
text=refund.comment,
)
refund.info_data = {
'gift_card': gc.pk,

View File

@@ -49,7 +49,7 @@ from pretix.base.signals import (
periodic_task, register_data_exporters, register_multievent_data_exporters,
)
from pretix.celery_app import app
from pretix.helpers import OF_SELF, repeatable_reads_transaction
from pretix.helpers import OF_SELF
from pretix.helpers.urls import build_absolute_uri
logger = logging.getLogger(__name__)
@@ -80,12 +80,7 @@ def export(self, event: Event, fileid: str, provider: str, form_data: Dict[str,
continue
ex = response(event, event.organizer, set_progress)
if ex.identifier == provider:
if ex.repeatable_read:
with repeatable_reads_transaction():
d = ex.render(form_data)
else:
d = ex.render(form_data)
d = ex.render(form_data)
if d is None:
raise ExportError(
gettext('Your export did not contain any data.')
@@ -156,11 +151,7 @@ def multiexport(self, organizer: Organizer, user: User, device: int, token: int,
gettext('You do not have sufficient permission to perform this export.')
)
if ex.repeatable_read:
with repeatable_reads_transaction():
d = ex.render(form_data)
else:
d = ex.render(form_data)
d = ex.render(form_data)
if d is None:
raise ExportError(
gettext('Your export did not contain any data.')
@@ -218,11 +209,7 @@ def _run_scheduled_export(schedule, context: Union[Event, Organizer], exporter,
try:
if not exporter:
raise ExportError("Export type not found.")
if exporter.repeatable_read:
with repeatable_reads_transaction():
d = exporter.render(schedule.export_form_data)
else:
d = exporter.render(schedule.export_form_data)
d = exporter.render(schedule.export_form_data)
if d is None:
raise ExportEmptyError(
gettext('Your export did not contain any data.')

View File

@@ -221,7 +221,7 @@ def import_orders(event: Event, fileid: str, settings: dict, locale: str, user,
for o in orders:
with language(o.locale, event.settings.region):
order_placed.send(event, order=o)
order_placed.send(event, order=o, bulk=True)
if o.status == Order.STATUS_PAID:
order_paid.send(event, order=o)

View File

@@ -1091,7 +1091,7 @@ def _create_order(event: Event, *, email: str, positions: List[CartPosition], no
for msg in meta_info.get('confirm_messages', []):
order.log_action('pretix.event.order.consent', data={'msg': msg})
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
return order, payments
@@ -2825,7 +2825,7 @@ class OrderChangeManager:
def _check_complete_cancel(self):
current = self.order.positions.count()
cancels = sum([
1 + o.position.addons.count() for o in self._operations if isinstance(o, self.CancelOperation)
1 + o.position.addons.filter(canceled=False).count() for o in self._operations if isinstance(o, self.CancelOperation)
]) + len([
o for o in self._operations if isinstance(o, self.SplitOperation)
])

View File

@@ -26,7 +26,7 @@ from itertools import zip_longest
import django_redis
from django.conf import settings
from django.db import connection, models
from django.db import models
from django.db.models import (
Case, Count, F, Func, Max, OuterRef, Q, Subquery, Sum, Value, When,
prefetch_related_objects,
@@ -64,8 +64,7 @@ class QuotaAvailability:
* count_cart (dict mapping quotas to ints)
"""
def __init__(self, count_waitinglist=True, ignore_closed=False, full_results=False, early_out=True,
allow_repeatable_read=False):
def __init__(self, count_waitinglist=True, ignore_closed=False, full_results=False, early_out=True):
"""
Initialize a new quota availability calculator
@@ -87,8 +86,6 @@ class QuotaAvailability:
keep the database-level quota cache up to date so backend overviews render quickly. If you
do not care about keeping the cache up to date, you can set this to ``False`` for further
performance improvements.
:param allow_repeatable_read: Allow to run this even in REPEATABLE READ mode, generally not advised.
"""
self._queue = []
self._count_waitinglist = count_waitinglist
@@ -98,7 +95,6 @@ class QuotaAvailability:
self._var_to_quotas = defaultdict(set)
self._early_out = early_out
self._quota_objects = {}
self._allow_repeatable_read = allow_repeatable_read
self.results = {}
self.count_paid_orders = defaultdict(int)
self.count_pending_orders = defaultdict(int)
@@ -123,10 +119,6 @@ class QuotaAvailability:
Compute the queued quotas. If ``allow_cache`` is set, results may also be taken from a cache that might
be a few minutes outdated. In this case, you may not rely on the results in the ``count_*`` properties.
"""
if not self._allow_repeatable_read and getattr(connection, "tx_in_repeatable_read", False):
raise ValueError("You cannot compute quotas in REPEATABLE READ mode unless you explicitly opted in to "
"do so.")
now_dt = now_dt or now()
quota_ids_set = {q.id for q in self._queue}
if not quota_ids_set:

View File

@@ -665,12 +665,13 @@ As with all event-plugin signals, the ``sender`` keyword argument will contain t
order_placed = EventPluginSignal()
"""
Arguments: ``order``
Arguments: ``order``, ``bulk``
This signal is sent out every time an order is placed. The order object is given
as the first argument. This signal is *not* sent out if an order is created through
splitting an existing order, so you can not expect to see all orders by listening
to this signal.
as the first argument. The ``bulk`` argument specifies whether the order was placed
as part of a bulk action, e.g. an import from a file.
This signal is *not* sent out if an order is created through splitting an existing order,
so you can not expect to see all orders by listening to this signal.
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
"""

View File

@@ -455,7 +455,7 @@ class OrderDataSyncSuccessLogEntryType(OrderDataSyncLogEntryType):
links.append(", ".join(
prov.get_external_link_html(logentry.event, obj['external_link_href'], obj['external_link_display_name'])
for obj in objs
if obj and 'external_link_href' in obj and 'external_link_display_name' in obj
if obj and obj.get('external_link_href') and obj.get('external_link_display_name')
))
return mark_safe(escape(super().display(logentry, data)) + "".join("<p>" + link + "</p>" for link in links))

View File

@@ -21,8 +21,7 @@
#
import contextlib
from django.conf import settings
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.core.exceptions import FieldDoesNotExist
from django.db import connection, transaction
from django.db.models import (
Aggregate, Expression, F, Field, Lookup, OrderBy, Value,
@@ -63,43 +62,6 @@ def casual_reads():
yield
@contextlib.contextmanager
def repeatable_reads_transaction():
"""
pretix, and Django, operate in the transaction isolation level READ COMMITTED by default. This is not a strong level
of isolation, but we NEED to use it: Otherwise e.g. our quota logic breaks, because we need to be able to get the
*current* number of tickets sold at any time in a transaction, not the number of tickets sold *before* our transaction
started.
However, this isolation mode has drawbacks, for example during reporting. When a user retrieves a report from the
system, it should return numbers that are consistent with each other. However, if the report makes multiple SQL
queries in READ COMMITTED mode, the results might be different for each query, causing numbers to be inconsistent
with each other.
This context manager creates a transaction that is running in REPEATABLE READ mode to avoid this problem.
**You should only make read-only queries during this transaction and not rely on quota calculations.**
"""
is_under_test = 'tests.testdummy' in settings.INSTALLED_APPS
try:
with transaction.atomic(durable=not is_under_test):
if not is_under_test:
# We're not running this in tests, where we can basically not use this since the test runner does its
# own transaction logic for efficiency
with connection.cursor() as cursor:
if 'postgresql' in settings.DATABASES['default']['ENGINE']:
cursor.execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;')
elif 'sqlite' in settings.DATABASES['default']['ENGINE']:
pass # noop
else:
raise ImproperlyConfigured("Cannot set transaction isolation mode on this database backend")
connection.tx_in_repeatable_read = True
yield
finally:
connection.tx_in_repeatable_read = False
class GroupConcat(Aggregate):
function = 'group_concat'
template = '%(function)s(%(distinct)s%(field)s, "%(separator)s")'

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-26 11:16+0000\n"
"PO-Revision-Date: 2025-08-30 02:00+0000\n"
"PO-Revision-Date: 2025-09-30 16:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix/"
"es/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.13\n"
"X-Generator: Weblate 5.13.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -810,28 +810,23 @@ msgstr ""
"Primero verifique la dirección de correo electrónico en su cuenta de cliente."
#: pretix/base/datasync/datasync.py:255
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" does not exist. Please check your {provider_name} "
"settings."
msgstr ""
"El campo «{field_name}» no es válido para {available_inputs}. Comprueba la "
"configuración de {provider_name}."
"El campo «{field_name}» no existe. Comprueba la configuración de "
"{provider_name}."
#: pretix/base/datasync/datasync.py:262
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" requires {required_input}, but only got "
"{available_inputs}. Please check your {provider_name} settings."
msgstr ""
"El campo «{field_name}» no es válido para {available_inputs}. Comprueba la "
"configuración de {provider_name}."
"El campo «{field_name}» requiere {required_input}, pero solo se ha "
"introducido {available_inputs}. Comprueba la configuración de "
"{provider_name}."
#: pretix/base/datasync/datasync.py:273
#, python-brace-format
@@ -3559,6 +3554,11 @@ msgid ""
"in accordance with the procedures and terms set forth in No. 89757/2018 of "
"April 30, 2018, issued by the Director of the Revenue Agency."
msgstr ""
"Este documento PDF es una copia visual de la factura y no constituye una "
"factura a efectos del IVA. La factura se emite en formato XML, transmitida "
"de acuerdo con los procedimientos y términos establecidos en el n.º 89757/"
"2018, de 30 de abril de 2018, emitido por el Director de la Agencia "
"Tributaria."
#: pretix/base/invoicing/pdf.py:141
#, python-format
@@ -3829,12 +3829,9 @@ msgid "Peppol participant ID"
msgstr "Identificador de participante Peppol"
#: pretix/base/invoicing/peppol.py:170
#, fuzzy
#| msgctxt "italian_invoice"
#| msgid "Fiscal code"
msgctxt "peppol_invoice"
msgid "Visual copy"
msgstr "Código fiscal"
msgstr "Copia visual"
#: pretix/base/invoicing/peppol.py:175
msgctxt "peppol_invoice"
@@ -3843,6 +3840,9 @@ msgid ""
"invoice for VAT purposes. The original invoice is issued in XML format and "
"transmitted through the Peppol network."
msgstr ""
"Este documento PDF es una copia visual de la factura y no constituye una "
"factura a efectos del IVA. La factura original se emite en formato XML y se "
"transmite a través de la red Peppol."
#: pretix/base/logentrytype_registry.py:43
msgid ""
@@ -14387,10 +14387,8 @@ msgid "Canceled (fully or with paid fee)"
msgstr "Cancelado (totalmente o con tarifa pagada)"
#: pretix/control/forms/filter.py:228
#, fuzzy
#| msgid "Cancel this position"
msgid "Canceled (at least one position)"
msgstr "Cancelar posición"
msgstr "Cancelado (al menos una posición)"
#: pretix/control/forms/filter.py:229
msgid "Cancellation requested"
@@ -17130,10 +17128,9 @@ msgid "The voucher has been deleted."
msgstr "El vale de compra fue eliminado."
#: pretix/control/logdisplay.py:584
#, fuzzy, python-brace-format
#| msgid "The voucher has been sent to {email} through the waiting list."
#, python-brace-format
msgid "The voucher has been assigned to {email} through the waiting list."
msgstr "El vale se ha enviado a {email} a través de la lista de espera."
msgstr "El vale se ha asignado a {email} a través de la lista de espera."
#: pretix/control/logdisplay.py:593
#, python-brace-format
@@ -27677,11 +27674,11 @@ msgstr ""
"próximos minutos."
#: pretix/control/views/datasync.py:90 pretix/control/views/datasync.py:104
#, fuzzy
#| msgid "The voucher \"{voucher}\" has been used in the meantime."
msgid ""
"The sync job could not be found. It may have been processed in the meantime."
msgstr "El vale de compra {voucher} ya ha sido utilizado."
msgstr ""
"No se ha encontrado la tarea de sincronización. Es posible que se haya "
"procesado mientras tanto."
#: pretix/control/views/datasync.py:93 pretix/control/views/datasync.py:107
msgid "The sync job is already in progress."
@@ -28674,12 +28671,12 @@ msgstr ""
"programado para {name}."
#: pretix/control/views/orders.py:2849 pretix/control/views/organizer.py:2207
#, fuzzy
#| msgid "You do not have sufficient permission to perform this export."
msgid ""
"Your user account does not have sufficient permission to run this report, "
"therefore you cannot schedule it."
msgstr "No tiene permiso suficiente para realizar esta exportación."
msgstr ""
"Su cuenta de usuario no tiene permisos suficientes para ejecutar este "
"informe, por lo que no puede programarlo."
#: pretix/control/views/orders.py:2902 pretix/control/views/organizer.py:2259
msgid ""
@@ -29044,17 +29041,14 @@ msgid "A date can not be deleted if orders already have been placed."
msgstr "No se puede borrar una fecha si ya se han realizado pedidos."
#: pretix/control/views/subevents.py:203
#, fuzzy
#| msgid ""
#| "The channel could not be deleted as some constraints (e.g. data created "
#| "by plug-ins) did not allow it."
msgctxt "subevent"
msgid ""
"The date could not be deleted as some constraints (e.g. data created by plug-"
"ins) did not allow it. The date was disabled instead."
msgstr ""
"El canal no ha podido borrarse porque algunas restricciones (por ejemplo, "
"datos creados por plug-ins) no lo permitían."
"La fecha no se pudo eliminar debido a que algunas restricciones (por "
"ejemplo, datos creados por complementos) no lo permitían. En su lugar, se "
"desactivó la fecha."
#: pretix/control/views/subevents.py:207
msgctxt "subevent"
@@ -33878,18 +33872,12 @@ msgstr ""
"formar un contrato válido."
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:192
#, fuzzy
#| msgid ""
#| "After you submitted your order using the button below, it will require "
#| "approval by the event organizer before it can be confirmed and forms a "
#| "valid contract."
msgid ""
"After you submitted your order using the button below, it will require "
"approval by the event organizer."
msgstr ""
"Después de enviar su pedido usando el botón a continuación, requerirá la "
"aprobación del organizador del evento antes de que pueda confirmarse y "
"formar un contrato válido."
"Después de enviar el pedido mediante el botón que aparece a continuación, "
"será necesario que el organizador del evento lo apruebe."
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:195
msgid ""
@@ -36448,10 +36436,8 @@ msgid "The selected date does not exist in this event series."
msgstr "La fecha seleccionada no existe en esta serie de eventos."
#: pretix/presale/views/widget.py:412
#, fuzzy
#| msgid "The selected seat \"{seat}\" is not available."
msgid "The selected date is not available."
msgstr "El asiento seleccionado {seat} no está disponible."
msgstr "La fecha seleccionada no está disponible."
#: pretix/presale/views/widget.py:476
#, python-format

View File

@@ -4,8 +4,8 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-26 11:16+0000\n"
"PO-Revision-Date: 2025-08-29 17:00+0000\n"
"Last-Translator: patch-works-be <webmaster@patch-works.be>\n"
"PO-Revision-Date: 2025-09-30 16:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
">\n"
"Language: fr\n"
@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.13\n"
"X-Generator: Weblate 5.13.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -810,28 +810,22 @@ msgstr ""
"mail dans votre espace client."
#: pretix/base/datasync/datasync.py:255
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" does not exist. Please check your {provider_name} "
"settings."
msgstr ""
"Le champ « {field_name} » n'est pas valide pour {available_inputs}. Veuillez "
"vérifier vos paramètres {provider_name}."
"Le champ « {field_name} » n'existe pas. Veuillez vérifier vos paramètres "
"pour {provider_name}."
#: pretix/base/datasync/datasync.py:262
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" requires {required_input}, but only got "
"{available_inputs}. Please check your {provider_name} settings."
msgstr ""
"Le champ « {field_name} » n'est pas valide pour {available_inputs}. Veuillez "
"vérifier vos paramètres {provider_name}."
"Le champ « {field_name} » nécessite {required_input}, mais n'a reçu que "
"{available_inputs}. Veuillez vérifier vos paramètres pour {provider_name}."
#: pretix/base/datasync/datasync.py:273
#, python-brace-format
@@ -3564,6 +3558,10 @@ msgid ""
"in accordance with the procedures and terms set forth in No. 89757/2018 of "
"April 30, 2018, issued by the Director of the Revenue Agency."
msgstr ""
"Ce document PDF est une copie visuelle de la facture et ne constitue pas une "
"facture aux fins de la TVA. La facture est émise au format XML, transmise "
"conformément aux procédures et conditions énoncées dans le n° 89757/2018 du "
"30 avril 2018, émis par le directeur de l'Agence des recettes."
#: pretix/base/invoicing/pdf.py:141
#, python-format
@@ -3834,12 +3832,9 @@ msgid "Peppol participant ID"
msgstr "Identifiant participant Peppol"
#: pretix/base/invoicing/peppol.py:170
#, fuzzy
#| msgctxt "italian_invoice"
#| msgid "Fiscal code"
msgctxt "peppol_invoice"
msgid "Visual copy"
msgstr "Code fiscal"
msgstr "Copie visuelle"
#: pretix/base/invoicing/peppol.py:175
msgctxt "peppol_invoice"
@@ -3848,6 +3843,9 @@ msgid ""
"invoice for VAT purposes. The original invoice is issued in XML format and "
"transmitted through the Peppol network."
msgstr ""
"Ce document PDF est une reproduction visuelle de la facture et ne constitue "
"pas une facture au sens de la TVA. La facture originale est émise au format "
"XML et transmise via le réseau Peppol."
#: pretix/base/logentrytype_registry.py:43
msgid ""
@@ -14513,10 +14511,8 @@ msgid "Canceled (fully or with paid fee)"
msgstr "Annulé (entièrement ou avec des frais payés)"
#: pretix/control/forms/filter.py:228
#, fuzzy
#| msgid "Cancel this position"
msgid "Canceled (at least one position)"
msgstr "Annuler cette position"
msgstr "Annulé (au moins pour une position)"
#: pretix/control/forms/filter.py:229
msgid "Cancellation requested"
@@ -17268,10 +17264,9 @@ msgid "The voucher has been deleted."
msgstr "Le bon a été supprimé."
#: pretix/control/logdisplay.py:584
#, fuzzy, python-brace-format
#| msgid "The voucher has been sent to {email} through the waiting list."
#, python-brace-format
msgid "The voucher has been assigned to {email} through the waiting list."
msgstr "Le bon a été envoyé à {email} via la liste d'attente."
msgstr "Le bon a été attribué à {email} via de la liste d'attente."
#: pretix/control/logdisplay.py:593
#, python-brace-format
@@ -27886,11 +27881,11 @@ msgstr ""
"les prochaines minutes."
#: pretix/control/views/datasync.py:90 pretix/control/views/datasync.py:104
#, fuzzy
#| msgid "The voucher \"{voucher}\" has been used in the meantime."
msgid ""
"The sync job could not be found. It may have been processed in the meantime."
msgstr "Le bon de réduction \"{voucher}\" a été utilisé entre-temps."
msgstr ""
"La tâche de synchronisation est introuvable. Elle a peut-être été traitée "
"entre-temps."
#: pretix/control/views/datasync.py:93 pretix/control/views/datasync.py:107
msgid "The sync job is already in progress."
@@ -28894,14 +28889,12 @@ msgstr ""
"planifié pour {name}."
#: pretix/control/views/orders.py:2849 pretix/control/views/organizer.py:2207
#, fuzzy
#| msgid "You do not have sufficient permission to perform this export."
msgid ""
"Your user account does not have sufficient permission to run this report, "
"therefore you cannot schedule it."
msgstr ""
"Vous ne disposez pas des autorisations suffisantes pour effectuer cette "
"exportation."
"Votre compte utilisateur ne dispose pas des autorisations suffisantes pour "
"exécuter ce rapport, vous ne pouvez donc pas le planifier."
#: pretix/control/views/orders.py:2902 pretix/control/views/organizer.py:2259
msgid ""
@@ -29272,17 +29265,14 @@ msgid "A date can not be deleted if orders already have been placed."
msgstr "Une date ne peut pas être supprimée si des ordres ont déjà été passés."
#: pretix/control/views/subevents.py:203
#, fuzzy
#| msgid ""
#| "The channel could not be deleted as some constraints (e.g. data created "
#| "by plug-ins) did not allow it."
msgctxt "subevent"
msgid ""
"The date could not be deleted as some constraints (e.g. data created by plug-"
"ins) did not allow it. The date was disabled instead."
msgstr ""
"Le canal de vente n'a pas pu être supprimé car certaines contraintes (par "
"exemple, les données créées par les plug-ins) ne le permettent pas."
"La date n'a pas pu être supprimée car certaines contraintes (par exemple, "
"les données créées par les plug-ins) ne le permettaient pas. La date a donc "
"été désactivée."
#: pretix/control/views/subevents.py:207
msgctxt "subevent"
@@ -34147,18 +34137,12 @@ msgstr ""
"puisse être confirmée et forme un contrat valide."
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:192
#, fuzzy
#| msgid ""
#| "After you submitted your order using the button below, it will require "
#| "approval by the event organizer before it can be confirmed and forms a "
#| "valid contract."
msgid ""
"After you submitted your order using the button below, it will require "
"approval by the event organizer."
msgstr ""
"Après avoir soumis votre commande en utilisant le bouton ci-dessous, elle "
"nécessitera lapprobation de lorganisateur de lévénement avant quelle "
"puisse être confirmée et forme un contrat valide."
"Une fois que vous aurez soumis votre commande à l'aide du bouton ci-dessous, "
"celle-ci devra être approuvée par l'organisateur de l'événement."
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:195
msgid ""
@@ -36776,10 +36760,8 @@ msgid "The selected date does not exist in this event series."
msgstr "La date sélectionnée nexiste pas dans cette série dévénements."
#: pretix/presale/views/widget.py:412
#, fuzzy
#| msgid "The selected seat \"{seat}\" is not available."
msgid "The selected date is not available."
msgstr "La place {seat} sélectionné n'est pas disponible."
msgstr "La date sélectionnée n'est pas disponible."
#: pretix/presale/views/widget.py:476
#, python-format

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-19 16:35+0000\n"
"PO-Revision-Date: 2025-09-27 16:00+0000\n"
"Last-Translator: Yasunobu YesNo Kawaguchi <kawaguti@gmail.com>\n"
"PO-Revision-Date: 2025-09-30 16:00+0000\n"
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/pretix/"
"ja/>\n"
"Language: ja\n"
@@ -796,28 +796,21 @@ msgstr ""
"メールアドレスを先に検証してください。"
#: pretix/base/datasync/datasync.py:255
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" does not exist. Please check your {provider_name} "
"settings."
msgstr ""
"フィールド\"{field_name}\"は{available_inputs}に対して有効ではありません。"
"{provider_name}の設定を確認してください。"
msgstr "フィールド「{field_name}」は存在しません。{provider_name}の設定を確認してくだ"
"さい。"
#: pretix/base/datasync/datasync.py:262
#, fuzzy, python-brace-format
#| msgid ""
#| "Field \"{field_name}\" is not valid for {available_inputs}. Please check "
#| "your {provider_name} settings."
#, python-brace-format
msgid ""
"Field \"{field_name}\" requires {required_input}, but only got "
"{available_inputs}. Please check your {provider_name} settings."
msgstr ""
"フィールド\"{field_name}\"は{available_inputs}に対して有効ではありません。"
"{provider_name}の設定を確認してください。"
"フィールド{field_name}」には{required_input}が必要ですが、{available_inputs"
"}しか取得できませんでした。{provider_name}の設定を確認してください。"
#: pretix/base/datasync/datasync.py:273
#, python-brace-format
@@ -3527,6 +3520,9 @@ msgid ""
"in accordance with the procedures and terms set forth in No. 89757/2018 of "
"April 30, 2018, issued by the Director of the Revenue Agency."
msgstr ""
"この PDF ドキュメントは請求書の画像情報の写しであり、VAT "
"のための請求書を構成するものではありません。請求書はXML形式で発行され、"
"2018年4月30日のNo. 89757/2018に定められた手順と条件に従って送信されます。"
#: pretix/base/invoicing/pdf.py:141
#, python-format
@@ -3794,12 +3790,9 @@ msgid "Peppol participant ID"
msgstr "Peppol参加者ID"
#: pretix/base/invoicing/peppol.py:170
#, fuzzy
#| msgctxt "italian_invoice"
#| msgid "Fiscal code"
msgctxt "peppol_invoice"
msgid "Visual copy"
msgstr "納税者番号"
msgstr "写しの画像"
#: pretix/base/invoicing/peppol.py:175
msgctxt "peppol_invoice"
@@ -3808,6 +3801,10 @@ msgid ""
"invoice for VAT purposes. The original invoice is issued in XML format and "
"transmitted through the Peppol network."
msgstr ""
"この PDF "
"ドキュメントは請求書の画像情報の写しであり、VATのための請求書を構成するもので"
"はありません。請求書の原本はXML形式で発行され、Peppolネットワークを介して送信"
"されます。"
#: pretix/base/logentrytype_registry.py:43
msgid ""
@@ -13970,10 +13967,8 @@ msgid "Canceled (fully or with paid fee)"
msgstr "キャンセル(全額返金または手数料を支払って)"
#: pretix/control/forms/filter.py:228
#, fuzzy
#| msgid "Cancel this position"
msgid "Canceled (at least one position)"
msgstr "このポジションをキャンセルします"
msgstr "キャンセル済み少なくとも1つのポジション"
#: pretix/control/forms/filter.py:229
msgid "Cancellation requested"
@@ -16622,10 +16617,9 @@ msgid "The voucher has been deleted."
msgstr "そのバウチャーは削除されました。"
#: pretix/control/logdisplay.py:584
#, fuzzy, python-brace-format
#| msgid "The voucher has been sent to {email} through the waiting list."
#, python-brace-format
msgid "The voucher has been assigned to {email} through the waiting list."
msgstr "バウチャー空席待ちリストを通じて{email}に送信されました。"
msgstr "バウチャーは、空席待ちリストを通じて{email}に割り当てられました。"
#: pretix/control/logdisplay.py:593
#, python-brace-format
@@ -26896,11 +26890,9 @@ msgid "The sync job has been enqueued and will run in the next minutes."
msgstr "同期ジョブがキューに追加されました。数分以内に実行されます。"
#: pretix/control/views/datasync.py:90 pretix/control/views/datasync.py:104
#, fuzzy
#| msgid "The voucher \"{voucher}\" has been used in the meantime."
msgid ""
"The sync job could not be found. It may have been processed in the meantime."
msgstr "そのバウチャー「{voucher}」はすでに使用されています。"
msgstr "同期ジョブが見つかりませんでした。その間に処理されていたかもしれません。"
#: pretix/control/views/datasync.py:93 pretix/control/views/datasync.py:107
msgid "The sync job is already in progress."
@@ -27862,12 +27854,11 @@ msgstr ""
"このメールに、{name}の新しい定期レポートを添付しています。"
#: pretix/control/views/orders.py:2849 pretix/control/views/organizer.py:2207
#, fuzzy
#| msgid "You do not have sufficient permission to perform this export."
msgid ""
"Your user account does not have sufficient permission to run this report, "
"therefore you cannot schedule it."
msgstr "このエクスポートを実行するための十分な権限がありません。"
msgstr "ユーザーアカウントにはこのレポートを実行するの十分な権限がないため、スケジ"
"ュールを設定できません。"
#: pretix/control/views/orders.py:2902 pretix/control/views/organizer.py:2259
msgid ""
@@ -28229,17 +28220,12 @@ msgid "A date can not be deleted if orders already have been placed."
msgstr "注文がすでにある場合、日付を削除することはできません。"
#: pretix/control/views/subevents.py:203
#, fuzzy
#| msgid ""
#| "The channel could not be deleted as some constraints (e.g. data created "
#| "by plug-ins) did not allow it."
msgctxt "subevent"
msgid ""
"The date could not be deleted as some constraints (e.g. data created by plug-"
"ins) did not allow it. The date was disabled instead."
msgstr ""
"チャンネルは削除できませんでした。プラグインによって作成されたデータなど、い"
"くつかの制約がそれを許可していませんでした。"
msgstr "日付は、いくつかの制約(プラグインによって作成されたデータなど)で許可されて"
"いないため、削除できませんでした。代わりに日付が無効になりました。"
#: pretix/control/views/subevents.py:207
msgctxt "subevent"
@@ -32934,17 +32920,10 @@ msgstr ""
"ます。その後、有効な契約が形成されます。"
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:192
#, fuzzy
#| msgid ""
#| "After you submitted your order using the button below, it will require "
#| "approval by the event organizer before it can be confirmed and forms a "
#| "valid contract."
msgid ""
"After you submitted your order using the button below, it will require "
"approval by the event organizer."
msgstr ""
"以下のボタンを使用して注文を送信した後、イベント主催者による承認が必要となり"
"ます。その後、有効な契約が形成されます。"
msgstr "下のボタンを使って注文を送信した後、イベント主催者の承認が必要になります。"
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:195
msgid ""
@@ -35434,10 +35413,8 @@ msgid "The selected date does not exist in this event series."
msgstr "選択された日付は、このイベントシリーズに存在しません。"
#: pretix/presale/views/widget.py:412
#, fuzzy
#| msgid "The selected seat \"{seat}\" is not available."
msgid "The selected date is not available."
msgstr "選択した座席 \"{seat}\"はご利用になれません。"
msgstr "選択した日付は利用できません。"
#: pretix/presale/views/widget.py:476
#, python-format

View File

@@ -7,16 +7,16 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-26 11:16+0000\n"
"PO-Revision-Date: 2025-08-26 19:00+0000\n"
"PO-Revision-Date: 2025-09-30 01:00+0000\n"
"Last-Translator: Jan Van Haver <jan.van.haver@gmail.com>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/"
">\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/>"
"\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.13\n"
"X-Generator: Weblate 5.13.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -3808,6 +3808,8 @@ msgstr "Evenementdatum: {date_range}"
msgid ""
"A Peppol participant ID always starts with a prefix, followed by a colon (:)."
msgstr ""
"Een Peppol deelnemer-ID begint altijd met een prefix, gevolgd door een "
"dubbele punt (:)."
#: pretix/base/invoicing/peppol.py:132
#, python-format
@@ -3815,6 +3817,8 @@ msgid ""
"The Peppol participant ID prefix %(number)s is not known to our system. "
"Please reach out to us if you are sure this ID is correct."
msgstr ""
"De prefix van de Peppol deelnemer-ID %(number)s is niet bekend in ons "
"systeem. Neem contact met ons op als u zeker weet dat deze ID correct is."
#: pretix/base/invoicing/peppol.py:136
#, python-format
@@ -3822,17 +3826,18 @@ msgid ""
"The Peppol participant ID does not match the validation rules for the prefix "
"%(number)s. Please reach out to us if you are sure this ID is correct."
msgstr ""
"De Peppol deelnemer-ID komt niet overeen met de validatieregels voor het "
"prefix %(number)s. Neem contact met ons op als u zeker weet dat deze ID "
"correct is."
#: pretix/base/invoicing/peppol.py:156
msgid "Peppol participant ID"
msgstr ""
msgstr "Peppol deelnemer-ID"
#: pretix/base/invoicing/peppol.py:170
#, fuzzy
#| msgid "Gift card code"
msgctxt "peppol_invoice"
msgid "Visual copy"
msgstr "Cadeauboncode"
msgstr "Visuele kopie"
#: pretix/base/invoicing/peppol.py:175
msgctxt "peppol_invoice"
@@ -3841,6 +3846,9 @@ msgid ""
"invoice for VAT purposes. The original invoice is issued in XML format and "
"transmitted through the Peppol network."
msgstr ""
"Dit PDF-document is een visuele kopie van de factuur en vormt geen factuur "
"voor BTW-doeleinden. De originele factuur wordt opgemaakt in XML-formaat en "
"verzonden via het Peppol-netwerk."
#: pretix/base/logentrytype_registry.py:43
msgid ""

View File

@@ -170,7 +170,7 @@ OPTIONS = OrderedDict([
'cols': 2,
'rows': 6,
'margins': [28.5 * mm, 30 * mm, 28.5 * mm, 30 * mm],
'offsets': [93 * mm, 60 * mm],
'offsets': [75 * mm, 40 * mm],
'pagesize': pagesizes.A4,
}),
('herma_50x80', {

View File

@@ -476,7 +476,6 @@ class CSVCheckinList(CheckInListMixin, ListExporter):
category = pgettext_lazy('export_category', 'Check-in')
description = gettext_lazy("Download a spreadsheet with all attendees that are included in a check-in list.")
featured = True
repeatable_read = False
@property
def additional_form_fields(self):
@@ -674,7 +673,6 @@ class CSVCheckinCodeList(CheckInListMixin, ListExporter):
category = pgettext_lazy('export_category', 'Check-in')
description = gettext_lazy("Download a spreadsheet with all valid check-in barcodes e.g. for import into a "
"different system. Does not included blocked codes or personal data.")
repeatable_read = False
@property
def additional_form_fields(self):
@@ -745,7 +743,6 @@ class CheckinLogList(ListExporter):
category = pgettext_lazy('export_category', 'Check-in')
description = gettext_lazy("Download a spreadsheet with one line for every scan that happened at your check-in "
"stations.")
repeatable_read = False
@property
def additional_form_fields(self):

View File

@@ -661,7 +661,6 @@ class OrderTaxListReport(MultiSheetListExporter):
verbose_name = gettext_lazy('Tax split list')
category = pgettext_lazy('export_category', 'Order data')
description = gettext_lazy("Download a spreadsheet with the tax amounts included in each order.")
repeatable_read = False
@property
def sheets(self):

View File

@@ -8,7 +8,7 @@
"name": "pretix",
"version": "0.0.0",
"dependencies": {
"@babel/core": "^7.28.3",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -18,18 +18,6 @@
"vue-template-compiler": "^2.7.16"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"dependencies": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -53,20 +41,20 @@
}
},
"node_modules/@babel/core": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helpers": "^7.28.3",
"@babel/parser": "^7.28.3",
"@babel/helpers": "^7.28.4",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.3",
"@babel/types": "^7.28.2",
"@babel/traverse": "^7.28.4",
"@babel/types": "^7.28.4",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -115,15 +103,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@babel/helper-annotate-as-pure": {
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
@@ -401,23 +380,23 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
"integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
"dependencies": {
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.2"
"@babel/types": "^7.28.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
"dependencies": {
"@babel/types": "^7.28.2"
"@babel/types": "^7.28.4"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1475,16 +1454,16 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.3",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.2",
"@babel/types": "^7.28.4",
"debug": "^4.3.1"
},
"engines": {
@@ -1492,9 +1471,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
@@ -1504,15 +1483,21 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dependencies": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
},
"engines": {
"node": ">=6.0.0"
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/remapping": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
@@ -1523,14 +1508,6 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
@@ -3802,15 +3779,6 @@
}
},
"dependencies": {
"@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"requires": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -3827,20 +3795,20 @@
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw=="
},
"@babel/core": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"requires": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helpers": "^7.28.3",
"@babel/parser": "^7.28.3",
"@babel/helpers": "^7.28.4",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.3",
"@babel/types": "^7.28.2",
"@babel/traverse": "^7.28.4",
"@babel/types": "^7.28.4",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -3870,17 +3838,6 @@
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"dependencies": {
"@jridgewell/gen-mapping": {
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"requires": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
}
}
},
"@babel/helper-annotate-as-pure": {
@@ -4074,20 +4031,20 @@
}
},
"@babel/helpers": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
"integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
"requires": {
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.2"
"@babel/types": "^7.28.4"
}
},
"@babel/parser": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
"requires": {
"@babel/types": "^7.28.2"
"@babel/types": "^7.28.4"
}
},
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
@@ -4718,35 +4675,44 @@
}
},
"@babel/traverse": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
"requires": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.3",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.2",
"@babel/types": "^7.28.4",
"debug": "^4.3.1"
}
},
"@babel/types": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
"requires": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
}
},
"@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"requires": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"@jridgewell/remapping": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"requires": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"@jridgewell/resolve-uri": {
@@ -4754,11 +4720,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
},
"@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="
},
"@jridgewell/sourcemap-codec": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",

View File

@@ -4,7 +4,7 @@
"private": true,
"scripts": {},
"dependencies": {
"@babel/core": "^7.28.3",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^16.0.1",

View File

@@ -64,7 +64,6 @@ from pretix.base.models.items import (
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
from pretix.base.services.orders import OrderError, cancel_order, perform_order
from pretix.base.services.quotas import QuotaAvailability
from pretix.helpers import repeatable_reads_transaction
from pretix.testutils.scope import classscope
@@ -100,29 +99,6 @@ class BaseQuotaTestCase(TestCase):
self.var3 = ItemVariation.objects.create(item=self.item3, value='Fancy')
@pytest.mark.django_db(transaction=True)
@scopes_disabled()
def test_verify_repeatable_read_check():
if 'sqlite' in settings.DATABASES['default']['ENGINE']:
pytest.skip('Not supported on SQLite')
o = Organizer.objects.create(name='Dummy', slug='dummy')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='tests.testdummy'
)
quota = Quota.objects.create(name="Test", size=2, event=event)
with repeatable_reads_transaction():
with pytest.raises(ValueError):
qa = QuotaAvailability(full_results=True)
qa.queue(quota)
qa.compute()
qa = QuotaAvailability(full_results=True, allow_repeatable_read=True)
qa.queue(quota)
qa.compute()
@pytest.mark.usefixtures("fakeredis_client")
class QuotaTestCase(BaseQuotaTestCase):
@classscope(attr='o')

View File

@@ -54,7 +54,7 @@ def test_sales_channel_all(event, item, order, checkin_list):
mode=AutoCheckinRule.MODE_PLACED,
all_sales_channels=True,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -67,12 +67,12 @@ def test_sales_channel_limit(event, item, order, checkin_list):
all_sales_channels=False,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert not order.positions.first().checkins.exists()
acr.limit_sales_channels.add(order.sales_channel)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -84,7 +84,7 @@ def test_items_all(event, item, order, checkin_list):
mode=AutoCheckinRule.MODE_PLACED,
all_products=True,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -97,12 +97,12 @@ def test_items_limit(event, item, order, checkin_list):
all_products=False,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert not order.positions.first().checkins.exists()
acr.limit_products.add(item)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -124,7 +124,7 @@ def test_variations_limit_mixed_order(event, item, order, checkin_list):
)
acr.limit_variations.add(var)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
assert not order.positions.last().checkins.exists()
@@ -143,19 +143,19 @@ def test_variations_limit(event, item, order, checkin_list):
all_products=False,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert not order.positions.first().checkins.exists()
acr.limit_variations.add(var)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
order.positions.first().checkins.all().delete()
acr.limit_products.add(item)
acr.limit_variations.clear()
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -170,7 +170,7 @@ def test_mode_placed(event, item, order, checkin_list):
order_paid.send(event, order=order)
assert not order.positions.first().checkins.exists()
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert order.positions.first().checkins.exists()
@@ -182,7 +182,7 @@ def test_mode_paid(event, item, order, checkin_list):
mode=AutoCheckinRule.MODE_PAID,
)
order_placed.send(event, order=order)
order_placed.send(event, order=order, bulk=False)
assert not order.positions.first().checkins.exists()
order_paid.send(event, order=order)