mirror of
https://github.com/pretix/pretix.git
synced 2026-05-14 16:44:06 +00:00
Compare commits
29 Commits
fix-mail-b
...
fix-transl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e6f18ab54 | ||
|
|
71edfa8e1a | ||
|
|
8303ba7808 | ||
|
|
5bbbf0334d | ||
|
|
14708eef80 | ||
|
|
952f121008 | ||
|
|
074d26cff3 | ||
|
|
6a9815ea5f | ||
|
|
01bd81a3cd | ||
|
|
6ae8cfe6f0 | ||
|
|
b60c8165c2 | ||
|
|
e460bf8bae | ||
|
|
b4f3d5c435 | ||
|
|
4bc8caae73 | ||
|
|
9183034c15 | ||
|
|
33ccd4342f | ||
|
|
301c47b761 | ||
|
|
b0d1c93fd9 | ||
|
|
70d59a960c | ||
|
|
e87b030427 | ||
|
|
994e4b410a | ||
|
|
bd6abbc280 | ||
|
|
ca7c982abd | ||
|
|
6010d7f9e5 | ||
|
|
ac08359a0e | ||
|
|
0aee73a9bd | ||
|
|
27183a26ee | ||
|
|
0acaed41be | ||
|
|
993acce05a |
@@ -31,7 +31,7 @@ RUN apt-get update && \
|
||||
mkdir /etc/pretix && \
|
||||
mkdir /data && \
|
||||
useradd -ms /bin/bash -d /pretix -u 15371 pretixuser && \
|
||||
chmod 0755 /pretix \
|
||||
chmod 0755 /pretix && \
|
||||
echo 'pretixuser ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers && \
|
||||
mkdir /static && \
|
||||
mkdir /etc/supervisord
|
||||
|
||||
@@ -86,7 +86,7 @@ individual commits, we use "Rebase and merge" instead. Merge commits should be a
|
||||
.. _PEP 8: https://legacy.python.org/dev/peps/pep-0008/
|
||||
.. _flake8: https://pypi.python.org/pypi/flake8
|
||||
.. _Django Coding Style: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/
|
||||
.. _translation: https://docs.djangoproject.com/en/1.11/topics/i18n/translation/
|
||||
.. _class-based views: https://docs.djangoproject.com/en/1.11/topics/class-based-views/
|
||||
.. _translation: https://docs.djangoproject.com/en/6.0/topics/i18n/translation/
|
||||
.. _class-based views: https://docs.djangoproject.com/en/6.0/topics/class-based-views/
|
||||
.. _pytest-style: https://docs.pytest.org/en/latest/assert.html
|
||||
.. _fixtures: https://docs.pytest.org/en/latest/fixture.html
|
||||
|
||||
@@ -115,10 +115,10 @@ class PluginsField(serializers.Field):
|
||||
|
||||
def to_representation(self, obj):
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
|
||||
active_plugins = set(obj.get_plugins())
|
||||
return sorted([
|
||||
p.module for p in get_all_plugins()
|
||||
if not p.name.startswith('.') and getattr(p, 'visible', True) and p.module in obj.get_plugins()
|
||||
if not p.name.startswith('.') and getattr(p, 'visible', True) and p.module in active_plugins
|
||||
])
|
||||
|
||||
def to_internal_value(self, data):
|
||||
|
||||
@@ -1160,7 +1160,7 @@ class Modern1Renderer(ClassicInvoiceRenderer):
|
||||
return stylesheet
|
||||
|
||||
def _draw_invoice_from(self, canvas):
|
||||
if not self.invoice.invoice_from:
|
||||
if not self.invoice.address_invoice_from:
|
||||
return
|
||||
c = [
|
||||
self._clean_text(l)
|
||||
|
||||
@@ -442,7 +442,7 @@ class AttendeeState(ImportColumn):
|
||||
|
||||
@property
|
||||
def verbose_name(self):
|
||||
return _('Attendee address') + ': ' + _('State')
|
||||
return _('Attendee address') + ': ' + pgettext('address', 'State')
|
||||
|
||||
def clean(self, value, previous_values):
|
||||
if value:
|
||||
|
||||
@@ -49,14 +49,39 @@ class PluginType(Enum):
|
||||
EXPORT = 4
|
||||
|
||||
|
||||
def plugin_is_available(meta, event=None, organizer=None):
|
||||
if not hasattr(meta.app, 'is_available'):
|
||||
return True
|
||||
|
||||
level = getattr(meta, "level", PLUGIN_LEVEL_EVENT)
|
||||
if level == PLUGIN_LEVEL_EVENT:
|
||||
if event:
|
||||
return meta.app.is_available(event)
|
||||
elif organizer:
|
||||
if not hasattr(organizer, '_plugin_availability_fallback_event'):
|
||||
with scope(organizer=organizer):
|
||||
setattr(organizer, '_plugin_availability_fallback_event', organizer.events.first())
|
||||
return (
|
||||
organizer._plugin_availability_fallback_event
|
||||
and meta.app.is_available(organizer._plugin_availability_fallback_event)
|
||||
)
|
||||
elif level == PLUGIN_LEVEL_ORGANIZER:
|
||||
if organizer:
|
||||
return meta.app.is_available(organizer)
|
||||
elif event:
|
||||
return meta.app.is_available(event.organizer)
|
||||
elif level == PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID and (event or organizer):
|
||||
return meta.app.is_available(event or organizer)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_all_plugins(*, event=None, organizer=None) -> List[type]:
|
||||
"""
|
||||
Returns the PretixPluginMeta classes of all plugins found in the installed Django apps.
|
||||
"""
|
||||
assert not event or not organizer
|
||||
plugins = []
|
||||
event_fallback = None
|
||||
event_fallback_used = False
|
||||
for app in apps.get_app_configs():
|
||||
if hasattr(app, 'PretixPluginMeta'):
|
||||
meta = app.PretixPluginMeta
|
||||
@@ -65,28 +90,8 @@ def get_all_plugins(*, event=None, organizer=None) -> List[type]:
|
||||
if app.name in settings.PRETIX_PLUGINS_EXCLUDE:
|
||||
continue
|
||||
|
||||
level = getattr(meta, "level", PLUGIN_LEVEL_EVENT)
|
||||
if level == PLUGIN_LEVEL_EVENT:
|
||||
if event and hasattr(app, 'is_available'):
|
||||
if not app.is_available(event):
|
||||
continue
|
||||
elif organizer and hasattr(app, 'is_available'):
|
||||
if not event_fallback_used:
|
||||
with scope(organizer=organizer):
|
||||
event_fallback = organizer.events.first()
|
||||
event_fallback_used = True
|
||||
if not event_fallback or not app.is_available(event_fallback):
|
||||
continue
|
||||
elif level == PLUGIN_LEVEL_ORGANIZER:
|
||||
if organizer and hasattr(app, 'is_available'):
|
||||
if not app.is_available(organizer):
|
||||
continue
|
||||
elif event and hasattr(app, 'is_available'):
|
||||
if not app.is_available(event.organizer):
|
||||
continue
|
||||
elif level == PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID and (event or organizer) and hasattr(app, 'is_available'):
|
||||
if not app.is_available(event or organizer):
|
||||
continue
|
||||
if not plugin_is_available(meta, event, organizer):
|
||||
continue
|
||||
|
||||
plugins.append(meta)
|
||||
return sorted(
|
||||
|
||||
@@ -162,12 +162,12 @@ error_messages = {
|
||||
'price_too_high': gettext_lazy('The entered price is to high.'),
|
||||
'voucher_invalid': gettext_lazy('This voucher code is not known in our database.'),
|
||||
'voucher_min_usages': ngettext_lazy(
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching products.',
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching product.',
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching products.',
|
||||
'number'
|
||||
),
|
||||
'voucher_min_usages_removed': ngettext_lazy(
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching products. '
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching product. '
|
||||
'We have therefore removed some positions from your cart that can no longer be purchased like this.',
|
||||
'The voucher code "%(voucher)s" can only be used if you select at least %(number)s matching products. '
|
||||
'We have therefore removed some positions from your cart that can no longer be purchased like this.',
|
||||
|
||||
@@ -1528,6 +1528,133 @@ class SubEventFilterForm(FilterForm):
|
||||
return self.event.organizer.meta_properties.filter(filter_allowed=True)
|
||||
|
||||
|
||||
class QuotaFilterForm(FilterForm):
|
||||
orders = {
|
||||
'-date': ('-subevent__date_from', 'name', 'pk'),
|
||||
'date': ('subevent__date_from', '-name', '-pk'),
|
||||
'size': ('size', 'name', 'pk'),
|
||||
'-size': ('-size', '-name', '-pk'),
|
||||
'name': ('name', 'pk'),
|
||||
'-name': ('-name', '-pk'),
|
||||
}
|
||||
subevent = forms.ModelChoiceField(
|
||||
label=pgettext_lazy('subevent', 'Date'),
|
||||
queryset=SubEvent.objects.none(),
|
||||
required=False,
|
||||
empty_label=pgettext_lazy('subevent', 'All dates')
|
||||
)
|
||||
date_from = forms.DateField(
|
||||
label=_('Date from'),
|
||||
required=False,
|
||||
widget=DatePickerWidget({
|
||||
'placeholder': _('Date from'),
|
||||
}),
|
||||
)
|
||||
date_until = forms.DateField(
|
||||
label=_('Date until'),
|
||||
required=False,
|
||||
widget=DatePickerWidget({
|
||||
'placeholder': _('Date until'),
|
||||
}),
|
||||
)
|
||||
time_from = forms.TimeField(
|
||||
label=_('Start time from'),
|
||||
required=False,
|
||||
widget=TimePickerWidget({}),
|
||||
)
|
||||
time_until = forms.TimeField(
|
||||
label=_('Start time until'),
|
||||
required=False,
|
||||
widget=TimePickerWidget({}),
|
||||
)
|
||||
weekday = forms.MultipleChoiceField(
|
||||
label=_('Weekday'),
|
||||
choices=(
|
||||
('2', _('Monday')),
|
||||
('3', _('Tuesday')),
|
||||
('4', _('Wednesday')),
|
||||
('5', _('Thursday')),
|
||||
('6', _('Friday')),
|
||||
('7', _('Saturday')),
|
||||
('1', _('Sunday')),
|
||||
),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
required=False
|
||||
)
|
||||
query = forms.CharField(
|
||||
label=_('Quota name'),
|
||||
widget=forms.TextInput(),
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.event.has_subevents:
|
||||
self.fields['date_from'].widget = DatePickerWidget()
|
||||
self.fields['date_until'].widget = DatePickerWidget()
|
||||
self.fields['subevent'].queryset = self.event.subevents.all()
|
||||
self.fields['subevent'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'event',
|
||||
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
|
||||
'event': self.event.slug,
|
||||
'organizer': self.event.organizer.slug,
|
||||
}),
|
||||
'data-placeholder': pgettext_lazy('subevent', 'All dates')
|
||||
}
|
||||
)
|
||||
self.fields['subevent'].widget.choices = self.fields['subevent'].choices
|
||||
else:
|
||||
del self.fields['subevent']
|
||||
del self.fields['date_from']
|
||||
del self.fields['date_until']
|
||||
del self.fields['time_from']
|
||||
del self.fields['time_until']
|
||||
del self.fields['weekday']
|
||||
|
||||
def filter_qs(self, qs):
|
||||
fdata = self.cleaned_data
|
||||
|
||||
if fdata.get('weekday'):
|
||||
qs = qs.annotate(wday=ExtractWeekDay('subevent__date_from')).filter(wday__in=fdata.get('weekday'))
|
||||
|
||||
if fdata.get('subevent'):
|
||||
qs = qs.filter(subevent=fdata["subevent"])
|
||||
|
||||
if fdata.get('query'):
|
||||
query = fdata.get('query')
|
||||
qs = qs.filter(name__icontains=query)
|
||||
|
||||
if fdata.get('date_until'):
|
||||
date_end = make_aware(datetime.combine(
|
||||
fdata.get('date_until') + timedelta(days=1),
|
||||
time(hour=0, minute=0, second=0, microsecond=0)
|
||||
), get_current_timezone())
|
||||
qs = qs.filter(
|
||||
Q(subevent__date_to__isnull=True, subevent__date_from__lt=date_end) |
|
||||
Q(subevent__date_to__isnull=False, subevent__date_to__lt=date_end)
|
||||
)
|
||||
if fdata.get('date_from'):
|
||||
date_start = make_aware(datetime.combine(
|
||||
fdata.get('date_from'),
|
||||
time(hour=0, minute=0, second=0, microsecond=0)
|
||||
), get_current_timezone())
|
||||
qs = qs.filter(subevent__date_from__gte=date_start)
|
||||
|
||||
if fdata.get('time_until'):
|
||||
qs = qs.filter(subevent__date_from__time__lte=fdata.get('time_until'))
|
||||
if fdata.get('time_from'):
|
||||
qs = qs.filter(subevent__date_from__time__gte=fdata.get('time_from'))
|
||||
|
||||
if fdata.get('ordering'):
|
||||
qs = qs.order_by(*get_deterministic_ordering(Quota, self.get_order_by()))
|
||||
else:
|
||||
qs = qs.order_by('-subevent__date_from', 'name', 'pk')
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
class OrganizerFilterForm(FilterForm):
|
||||
orders = {
|
||||
'slug': 'slug',
|
||||
|
||||
@@ -43,6 +43,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.db.models import Max, Q
|
||||
from django.forms import ChoiceField, RadioSelect
|
||||
from django.forms.formsets import DELETION_FIELD_NAME
|
||||
from django.forms.utils import ErrorDict
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import escape, format_html
|
||||
@@ -375,6 +376,60 @@ class QuotaForm(I18nModelForm):
|
||||
return inst
|
||||
|
||||
|
||||
class QuotaBulkEditForm(QuotaForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mixed_values = kwargs.pop('mixed_values')
|
||||
self.queryset = kwargs.pop('queryset')
|
||||
super().__init__(**kwargs)
|
||||
self.fields.pop("subevent", None) # Would add extra complexity and it's hard to imagine a use case for that
|
||||
self.fields["name"].required = False
|
||||
self.fields["itemvars"].required = False
|
||||
|
||||
def clean(self):
|
||||
d = super().clean()
|
||||
if self.prefix + "name" in self.data.getlist('_bulk') and not d.get("name"):
|
||||
raise ValidationError({"name": _("This field is required.")})
|
||||
if self.prefix + "itemvars" in self.data.getlist('_bulk') and not d.get("itemvars"):
|
||||
raise ValidationError({"itemvars": _("This field is required.")})
|
||||
return d
|
||||
|
||||
def save(self, commit=True):
|
||||
objs = list(self.queryset)
|
||||
fields = set()
|
||||
|
||||
for k in self.fields:
|
||||
cb_val = self.prefix + k
|
||||
if cb_val not in self.data.getlist('_bulk'):
|
||||
continue
|
||||
|
||||
fields.add(k)
|
||||
if k == 'itemvars':
|
||||
selected_items = set(list(self.event.items.filter(id__in=[
|
||||
i.split('-')[0] for i in self.cleaned_data['itemvars']
|
||||
])))
|
||||
selected_variations = list(ItemVariation.objects.filter(item__event=self.event, id__in=[
|
||||
i.split('-')[1] for i in self.cleaned_data['itemvars'] if '-' in i
|
||||
]))
|
||||
for obj in objs:
|
||||
obj.items.set(selected_items)
|
||||
obj.variations.set(selected_variations)
|
||||
else:
|
||||
for obj in objs:
|
||||
setattr(obj, k, self.cleaned_data[k])
|
||||
|
||||
fields = [f for f in fields if f != 'itemvars']
|
||||
if fields:
|
||||
Quota.objects.bulk_update(objs, fields, 200)
|
||||
|
||||
def full_clean(self):
|
||||
if len(self.data) == 0:
|
||||
# form wasn't submitted
|
||||
self._errors = ErrorDict()
|
||||
return
|
||||
super().full_clean()
|
||||
|
||||
|
||||
class ItemCreateForm(I18nModelForm):
|
||||
NONE = 'none'
|
||||
EXISTING = 'existing'
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block content %}
|
||||
<h1>
|
||||
{% trans "Change multiple quotas" %}
|
||||
<small>
|
||||
{% blocktrans trimmed with number=quotas.count %}
|
||||
{{ number }} selected
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</h1>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<div class="hidden">
|
||||
{% for d in quotas %}
|
||||
<input type="hidden" name="quota" value="{{ d.pk }}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
<fieldset>
|
||||
<legend>{% trans "General information" %}</legend>
|
||||
{% bootstrap_field form.name layout="bulkedit" %}
|
||||
{% bootstrap_field form.size layout="bulkedit" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Items" %}</legend>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Please select the products or product variations this quota should be applied to. If you apply two
|
||||
quotas to the same product, it will only be available if <strong>both</strong> quotas have capacity
|
||||
left.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% bootstrap_field form.itemvars layout="bulkedit" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Advanced options" %}</legend>
|
||||
{% bootstrap_field form.close_when_sold_out layout="bulkedit" %}
|
||||
{% bootstrap_field form.release_after_exit layout="bulkedit" %}
|
||||
{% bootstrap_field form.ignore_for_event_availability layout="bulkedit" %}
|
||||
</fieldset>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,34 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Delete quotas" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Delete quotas" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% if allowed %}
|
||||
<p>{% blocktrans trimmed count num=allowed|length %}
|
||||
Are you sure you want to delete the following quota?
|
||||
{% plural %}
|
||||
Are you sure you want to delete the following {{ num }} quotas?
|
||||
{% endblocktrans %}</p>
|
||||
<ul>
|
||||
{% for q in allowed %}
|
||||
<li>
|
||||
{{ q }} {% if q.subevent %}({{ q.subevent }}){% endif %}
|
||||
<input type="hidden" name="quota" value="{{ q.pk }}">
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<div class="form-group submit-group">
|
||||
<a href="{% url "control:event.items.quotas" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-default btn-cancel">
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger btn-save" value="delete_confirm" name="action">
|
||||
{% trans "Delete" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "pretixcontrol/items/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load urlreplace %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Quotas" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Quotas" %}</h1>
|
||||
@@ -13,21 +14,12 @@
|
||||
number of a specific ticket type at the same time.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if quotas|length == 0 %}
|
||||
{% if quotas|length == 0 and not filter_form.filtered %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% if request.GET.subevent %}
|
||||
{% trans "Your search did not match any quotas." %}
|
||||
{% else %}
|
||||
{% blocktrans trimmed %}
|
||||
You haven't created any quotas yet.
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% blocktrans trimmed %}
|
||||
You haven't created any quotas yet.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
{% if 'event.items:write' in request.eventpermset %}
|
||||
@@ -36,79 +28,160 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Filter" %}
|
||||
</h3>
|
||||
</div>
|
||||
<form class="panel-body filter-form" action="" method="get">
|
||||
<div class="row">
|
||||
<div class="{% if not filter_form.subevent %}col-lg-6{% else %}col-lg-2{% endif %} col-md-6 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.query %}
|
||||
</div>
|
||||
{% if filter_form.subevent %}
|
||||
<div class="col-lg-2 col-md-6 col-md-2 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.subevent %}
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.date_from %}
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.date_until %}
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.time_from %}
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.time_until %}
|
||||
</div>
|
||||
<div class="col-xs-12 one-line-checkboxes">
|
||||
{% bootstrap_field filter_form.weekday %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="text-right flip">
|
||||
<button class="btn btn-primary btn-lg" type="submit">
|
||||
<span class="fa fa-filter"></span>
|
||||
{% trans "Filter" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% if 'event.items:write' in request.eventpermset %}
|
||||
<p>
|
||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-quotas">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Quota name" %}
|
||||
<a href="?{% url_replace request 'ordering' '-name' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'name' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th>{% trans "Products" %}</th>
|
||||
{% if request.event.has_subevents %}
|
||||
<th>{% trans "Date" context "subevent" %}
|
||||
<a href="?{% url_replace request 'ordering' '-date' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'date' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
{% endif %}
|
||||
<th>{% trans "Total capacity" %}
|
||||
<a href="?{% url_replace request 'ordering' '-size' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'size' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th>{% trans "Capacity left" %}</th>
|
||||
<th class="action-col-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for q in quotas %}
|
||||
<form action="{% url "control:event.items.quotas.bulkaction" organizer=request.event.organizer.slug event=request.event.slug %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% for field in filter_form %}
|
||||
{{ field.as_hidden }}
|
||||
{% endfor %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-quotas">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>
|
||||
<strong><a href="{% url "control:event.items.quotas.show" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}">{{ q.name }}</a></strong>
|
||||
{% if q.ignore_for_event_availability %}
|
||||
<span class="fa fa-eye-slash text-muted" data-toggle="tooltip" title="{% trans "Ignore this quota when determining event availability" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
{% for item in q.cached_items %}
|
||||
{% if not item.has_variations %}
|
||||
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for v in q.variations.all %}
|
||||
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=v.item.id %}#tab-0-3-open">
|
||||
{{ v.item }} – {{ v }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
{% if request.event.has_subevents %}
|
||||
<td>
|
||||
{{ q.subevent.name }} – {{ q.subevent.get_date_range_display_with_times }}
|
||||
</td>
|
||||
{% if "event.items:write" in request.eventpermset %}
|
||||
<th>
|
||||
<label aria-label="{% trans "select all rows for batch-operation" %}" class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||
</th>
|
||||
{% endif %}
|
||||
<td>{% if q.size == None %}Unlimited{% else %}{{ q.size }}{% endif %}</td>
|
||||
<td>{% include "pretixcontrol/items/fragment_quota_availability.html" with availability=q.cached_avail closed=q.closed %}</td>
|
||||
<td class="text-right flip">
|
||||
{% if 'event.items:write' in request.eventpermset %}
|
||||
<a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ q.id }}"
|
||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||
<span class="fa fa-copy"></span>
|
||||
</a>
|
||||
<a href="{% url "control:event.items.quotas.delete" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<th>{% trans "Quota name" %}
|
||||
<a href="?{% url_replace request 'filter-ordering' '-name' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'filter-ordering' 'name' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th>{% trans "Products" %}</th>
|
||||
{% if request.event.has_subevents %}
|
||||
<th>{% trans "Date" context "subevent" %}
|
||||
<a href="?{% url_replace request 'filter-ordering' '-date' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'filter-ordering' 'date' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
{% endif %}
|
||||
<th>{% trans "Total capacity" %}
|
||||
<a href="?{% url_replace request 'filter-ordering' '-size' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'filter-ordering' 'size' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th>{% trans "Capacity left" %}</th>
|
||||
<th class="action-col-2"></th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% if "event.items:write" in request.eventpermset and page_obj.paginator.num_pages > 1 %}
|
||||
<tr class="table-select-all warning hidden">
|
||||
<td>
|
||||
<input type="checkbox" name="__ALL" id="__all" data-results-total="{{ page_obj.paginator.count }}">
|
||||
</td>
|
||||
<td colspan="6">
|
||||
<label for="__all">
|
||||
{% trans "Select all results on other pages as well" %}
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for q in quotas %}
|
||||
<tr>
|
||||
{% if "event.items:write" in request.eventpermset %}
|
||||
<td>
|
||||
<label aria-label="{% trans "select row for batch-operation" %}" class="batch-select-label"><input type="checkbox" name="quota" class="batch-select-checkbox" value="{{ q.pk }}"/></label>
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
<strong><a href="{% url "control:event.items.quotas.show" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}">{{ q.name }}</a></strong>
|
||||
{% if q.ignore_for_event_availability %}
|
||||
<span class="fa fa-eye-slash text-muted" data-toggle="tooltip" title="{% trans "Ignore this quota when determining event availability" %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
{% for item in q.cached_items %}
|
||||
{% if not item.has_variations %}
|
||||
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.id %}">{{ item }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for v in q.variations.all %}
|
||||
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=v.item.id %}#tab-0-3-open">
|
||||
{{ v.item }} – {{ v }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
{% if request.event.has_subevents %}
|
||||
<td>
|
||||
{{ q.subevent.name }} – {{ q.subevent.get_date_range_display_with_times }}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>{% if q.size == None %}Unlimited{% else %}{{ q.size }}{% endif %}</td>
|
||||
<td>{% include "pretixcontrol/items/fragment_quota_availability.html" with availability=q.cached_avail closed=q.closed %}</td>
|
||||
<td class="text-right flip">
|
||||
{% if 'event.items:write' in request.eventpermset %}
|
||||
<a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ q.id }}"
|
||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||
<span class="fa fa-copy"></span>
|
||||
</a>
|
||||
<a href="{% url "control:event.items.quotas.delete" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% if "event.items:write" in request.eventpermset %}
|
||||
<div class="batch-select-actions">
|
||||
<button type="submit" class="btn btn-danger btn-save" name="action" value="delete">
|
||||
<i class="fa fa-trash"></i>{% trans "Delete selected" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary btn-save" name="action" value="edit"
|
||||
formaction="{% url "control:event.items.quotas.bulkedit" organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
<i class="fa fa-edit"></i>{% trans "Edit selected" %}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -471,7 +471,9 @@
|
||||
{% endif %}
|
||||
{% if line.subevent %}
|
||||
<br/>
|
||||
<span class="fa fa-calendar fa-fw"></span> {{ line.subevent.name }} · {{ line.subevent.get_date_range_display_with_times }}
|
||||
<span class="fa fa-calendar fa-fw"></span>
|
||||
<a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=line.subevent_id %}">{{ line.subevent.name }}</a>
|
||||
· {{ line.subevent.get_date_range_display_with_times }}
|
||||
{% endif %}
|
||||
{% if line.used_membership %}
|
||||
<br /><span class="fa fa-id-card fa-fw" aria-hidden="true"></span>
|
||||
|
||||
@@ -349,6 +349,8 @@ urlpatterns = [
|
||||
name='event.items.questions.edit'),
|
||||
re_path(r'^questions/add$', item.QuestionCreate.as_view(), name='event.items.questions.add'),
|
||||
re_path(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'),
|
||||
re_path(r'^quotas/bulk_action$', item.QuotaBulkAction.as_view(), name='event.items.quotas.bulkaction'),
|
||||
re_path(r'^quotas/bulk_edit$', item.QuotaBulkUpdateView.as_view(), name='event.items.quotas.bulkedit'),
|
||||
re_path(r'^quotas/(?P<quota>\d+)/$', item.QuotaView.as_view(), name='event.items.quotas.show'),
|
||||
re_path(r'^quotas/select$', typeahead.quotas_select2, name='event.items.quotas.select2'),
|
||||
re_path(r'^quotas/(?P<quota>\d+)/change$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
|
||||
|
||||
@@ -41,21 +41,22 @@ from json.decoder import JSONDecodeError
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.files import File
|
||||
from django.db import transaction
|
||||
from django.db import models, transaction
|
||||
from django.db.models import (
|
||||
Count, Exists, F, OuterRef, Prefetch, ProtectedError, Q,
|
||||
Count, Exists, F, OuterRef, Prefetch, ProtectedError, Q, Subquery, Value,
|
||||
)
|
||||
from django.db.models.functions import Cast, Concat
|
||||
from django.forms.models import inlineformset_factory
|
||||
from django.http import (
|
||||
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect,
|
||||
)
|
||||
from django.shortcuts import redirect
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import resolve, reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.views.generic import ListView
|
||||
from django.views.generic import FormView, ListView, View
|
||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from django_countries.fields import Country
|
||||
|
||||
@@ -65,7 +66,7 @@ from pretix.api.serializers.item import (
|
||||
)
|
||||
from pretix.base.forms import I18nFormSet
|
||||
from pretix.base.models import (
|
||||
CartPosition, Item, ItemCategory, ItemProgramTime, ItemVariation,
|
||||
CartPosition, Item, ItemCategory, ItemProgramTime, ItemVariation, LogEntry,
|
||||
OrderPosition, Question, QuestionAnswer, QuestionOption, Quota,
|
||||
SeatCategoryMapping, Voucher,
|
||||
)
|
||||
@@ -74,12 +75,15 @@ from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
|
||||
from pretix.base.services.quotas import QuotaAvailability
|
||||
from pretix.base.services.tickets import invalidate_cache
|
||||
from pretix.base.signals import quota_availability
|
||||
from pretix.control.forms.filter import QuestionAnswerFilterForm
|
||||
from pretix.control.forms.filter import (
|
||||
QuestionAnswerFilterForm, QuotaFilterForm,
|
||||
)
|
||||
from pretix.control.forms.item import (
|
||||
CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemBundleForm,
|
||||
ItemBundleFormSet, ItemCreateForm, ItemMetaValueForm, ItemProgramTimeForm,
|
||||
ItemProgramTimeFormSet, ItemUpdateForm, ItemVariationForm,
|
||||
ItemVariationsFormSet, QuestionForm, QuestionOptionForm, QuotaForm,
|
||||
ItemVariationsFormSet, QuestionForm, QuestionOptionForm, QuotaBulkEditForm,
|
||||
QuotaForm,
|
||||
)
|
||||
from pretix.control.permissions import (
|
||||
EventPermissionRequiredMixin, event_permission_required,
|
||||
@@ -87,6 +91,7 @@ from pretix.control.permissions import (
|
||||
from pretix.control.signals import item_forms, item_formsets
|
||||
from pretix.helpers.models import modelcopy
|
||||
|
||||
from ...helpers import GroupConcat
|
||||
from ...helpers.compat import CompatDeleteView
|
||||
from . import ChartContainingView, CreateView, PaginationMixin, UpdateView
|
||||
|
||||
@@ -831,13 +836,38 @@ class QuestionCreate(EventPermissionRequiredMixin, QuestionMixin, CreateView):
|
||||
return ret
|
||||
|
||||
|
||||
class QuotaList(PaginationMixin, ListView):
|
||||
class QuotaQueryMixin:
|
||||
|
||||
@cached_property
|
||||
def request_data(self):
|
||||
if self.request.method == "POST":
|
||||
return self.request.POST
|
||||
return self.request.GET
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.event.quotas
|
||||
if self.filter_form.is_valid():
|
||||
qs = self.filter_form.filter_qs(qs)
|
||||
|
||||
if 'quota' in self.request_data and '__ALL' not in self.request_data:
|
||||
qs = qs.filter(
|
||||
id__in=self.request_data.getlist('quota')
|
||||
)
|
||||
|
||||
return qs
|
||||
|
||||
@cached_property
|
||||
def filter_form(self):
|
||||
return QuotaFilterForm(data=self.request_data, prefix='filter', event=self.request.event)
|
||||
|
||||
|
||||
class QuotaList(PaginationMixin, QuotaQueryMixin, ListView):
|
||||
model = Quota
|
||||
context_object_name = 'quotas'
|
||||
template_name = 'pretixcontrol/items/quotas.html'
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.event.quotas.prefetch_related(
|
||||
return super().get_queryset().prefetch_related(
|
||||
Prefetch(
|
||||
"items",
|
||||
queryset=Item.objects.annotate(
|
||||
@@ -852,28 +882,10 @@ class QuotaList(PaginationMixin, ListView):
|
||||
queryset=self.request.event.subevents.all()
|
||||
)
|
||||
)
|
||||
if self.request.GET.get("subevent", "") != "":
|
||||
s = self.request.GET.get("subevent", "")
|
||||
qs = qs.filter(subevent_id=s)
|
||||
|
||||
valid_orders = {
|
||||
'-date': ('-subevent__date_from', 'name', 'pk'),
|
||||
'date': ('subevent__date_from', '-name', '-pk'),
|
||||
'size': ('size', 'name', 'pk'),
|
||||
'-size': ('-size', '-name', '-pk'),
|
||||
'name': ('name', 'pk'),
|
||||
'-name': ('-name', '-pk'),
|
||||
}
|
||||
|
||||
if self.request.GET.get("ordering", "-date") in valid_orders:
|
||||
qs = qs.order_by(*valid_orders[self.request.GET.get("ordering", "-date")])
|
||||
else:
|
||||
qs = qs.order_by('name', 'subevent__date_from', 'pk')
|
||||
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
ctx['filter_form'] = self.filter_form
|
||||
|
||||
qa = QuotaAvailability()
|
||||
qa.queue(*ctx['quotas'])
|
||||
@@ -884,6 +896,165 @@ class QuotaList(PaginationMixin, ListView):
|
||||
return ctx
|
||||
|
||||
|
||||
class QuotaBulkAction(QuotaQueryMixin, EventPermissionRequiredMixin, View):
|
||||
permission = 'event.items:write'
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get('action') == 'delete':
|
||||
return render(request, 'pretixcontrol/items/quota_delete_bulk.html', {
|
||||
'allowed': self.get_queryset().select_related("subevent"),
|
||||
})
|
||||
elif request.POST.get('action') == 'delete_confirm':
|
||||
log_entries = []
|
||||
to_delete = []
|
||||
for obj in self.get_queryset():
|
||||
log_entries.append(obj.log_action('pretix.event.quota.deleted', user=self.request.user, save=False))
|
||||
to_delete.append(obj.pk)
|
||||
|
||||
if to_delete:
|
||||
LogEntry.bulk_create_and_postprocess(log_entries)
|
||||
Quota.objects.filter(pk__in=to_delete).delete()
|
||||
messages.success(request, _('The selected quotas have been deleted or disabled.'))
|
||||
return redirect(self.get_success_url())
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.items.quotas', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
|
||||
class QuotaBulkUpdateView(QuotaQueryMixin, EventPermissionRequiredMixin, FormView):
|
||||
template_name = 'pretixcontrol/items/quota_bulk_edit.html'
|
||||
permission = 'event.items:write'
|
||||
context_object_name = 'quota'
|
||||
form_class = QuotaBulkEditForm
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().prefetch_related(None).order_by()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return HttpResponse(status=405)
|
||||
|
||||
@cached_property
|
||||
def is_submitted(self):
|
||||
# Usually, django considers a form "bound" / "submitted" on every POST request. However, this view is always
|
||||
# called with POST method, even if just to pass the selection of objects to work on, so we want to modify
|
||||
# that behaviour
|
||||
return '_bulk' in self.request.POST
|
||||
|
||||
def get_form_kwargs(self):
|
||||
initial = {}
|
||||
mixed_values = set()
|
||||
qs = self.get_queryset().annotate(
|
||||
items_list=Subquery(
|
||||
Quota.items.through.objects.filter(
|
||||
quota_id=OuterRef('pk'),
|
||||
item__variations__isnull=True,
|
||||
).order_by().values('quota_id').annotate(
|
||||
g=GroupConcat('item_id', separator=',', ordered=True)
|
||||
).values('g')
|
||||
),
|
||||
vars_list=Subquery(
|
||||
Quota.variations.through.objects.filter(
|
||||
quota_id=OuterRef('pk')
|
||||
).order_by().values('quota_id').annotate(
|
||||
g=GroupConcat(
|
||||
Concat(
|
||||
Cast(F('itemvariation__item_id'), output_field=models.TextField()),
|
||||
Value('-', output_field=models.TextField()),
|
||||
Cast(F('itemvariation_id'), output_field=models.TextField()),
|
||||
),
|
||||
separator=',',
|
||||
ordered=True
|
||||
)
|
||||
).values('g')
|
||||
),
|
||||
)
|
||||
|
||||
fields = {
|
||||
'name': 'name',
|
||||
'size': 'size',
|
||||
'subevent': 'subevent',
|
||||
'close_when_sold_out': 'close_when_sold_out',
|
||||
'release_after_exit': 'release_after_exit',
|
||||
'ignore_for_event_availability': 'ignore_for_event_availability',
|
||||
}
|
||||
for k, f in fields.items():
|
||||
existing_values = list(qs.order_by(f).values(f).annotate(c=Count('*')))
|
||||
if len(existing_values) == 1:
|
||||
initial[k] = existing_values[0][f]
|
||||
elif len(existing_values) > 1:
|
||||
mixed_values.add(k)
|
||||
initial[k] = None
|
||||
|
||||
item_values = list(qs.order_by("items_list").values("items_list").annotate(c=Count('*')))
|
||||
var_values = list(qs.order_by("vars_list").values("vars_list").annotate(c=Count('*')))
|
||||
if len(item_values) > 1 or len(var_values) > 1:
|
||||
mixed_values.add("itemvars")
|
||||
else:
|
||||
initial["itemvars"] = [iv for iv in (item_values[0]["items_list"] or "").split(",") + (var_values[0]["vars_list"] or "").split(",") if iv]
|
||||
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['event'] = self.request.event
|
||||
kwargs['prefix'] = 'bulkedit'
|
||||
kwargs['initial'] = initial
|
||||
kwargs['queryset'] = self.get_queryset()
|
||||
kwargs['mixed_values'] = mixed_values
|
||||
if not self.is_submitted:
|
||||
kwargs['data'] = None
|
||||
kwargs['files'] = None
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('control:event.items.quotas', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
@transaction.atomic()
|
||||
def form_valid(self, form):
|
||||
log_entries = []
|
||||
|
||||
# Main form
|
||||
form.save()
|
||||
data = {
|
||||
k: v
|
||||
for k, v in form.cleaned_data.items()
|
||||
if k in form.changed_data
|
||||
}
|
||||
data['_raw_bulk_data'] = self.request.POST.dict()
|
||||
for obj in self.get_queryset():
|
||||
log_entries.append(
|
||||
obj.log_action('pretix.event.quota.changed', data=data, user=self.request.user, save=False)
|
||||
)
|
||||
|
||||
LogEntry.bulk_create_and_postprocess(log_entries)
|
||||
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['quotas'] = self.get_queryset()
|
||||
ctx['bulk_selected'] = self.request.POST.getlist("_bulk")
|
||||
return ctx
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
is_valid = (
|
||||
self.is_submitted and
|
||||
form.is_valid()
|
||||
)
|
||||
if is_valid:
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
if self.is_submitted:
|
||||
messages.error(self.request, _('We could not save your changes. See below for details.'))
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class QuotaCreate(EventPermissionRequiredMixin, CreateView):
|
||||
model = Quota
|
||||
form_class = QuotaForm
|
||||
|
||||
@@ -102,7 +102,7 @@ from pretix.base.models.organizer import (
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.plugins import (
|
||||
PLUGIN_LEVEL_EVENT, PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID,
|
||||
PLUGIN_LEVEL_ORGANIZER,
|
||||
PLUGIN_LEVEL_ORGANIZER, plugin_is_available,
|
||||
)
|
||||
from pretix.base.services.export import (
|
||||
init_organizer_exporters, multiexport, scheduled_organizer_export,
|
||||
@@ -597,6 +597,13 @@ class OrganizerCreate(CreateView):
|
||||
})
|
||||
|
||||
|
||||
def available_plugins(organizer):
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
|
||||
return (p for p in get_all_plugins(organizer=organizer) if not p.name.startswith('.')
|
||||
and getattr(p, 'visible', True))
|
||||
|
||||
|
||||
class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
||||
model = Organizer
|
||||
context_object_name = 'organizer'
|
||||
@@ -606,12 +613,6 @@ class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
||||
def get_object(self, queryset=None) -> Organizer:
|
||||
return self.request.organizer
|
||||
|
||||
def available_plugins(self, organizer):
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
|
||||
return (p for p in get_all_plugins(organizer=organizer) if not p.name.startswith('.')
|
||||
and getattr(p, 'visible', True))
|
||||
|
||||
def prepare_links(self, pluginmeta, key):
|
||||
links = getattr(pluginmeta, key, [])
|
||||
try:
|
||||
@@ -637,7 +638,7 @@ class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
||||
from pretix.base.plugins import CATEGORY_LABELS, CATEGORY_ORDER
|
||||
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
plugins = list(self.available_plugins(self.object))
|
||||
plugins = list(available_plugins(self.object))
|
||||
|
||||
active_counter = Counter()
|
||||
events_total = 0
|
||||
@@ -685,7 +686,7 @@ class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
||||
self.object = self.get_object()
|
||||
|
||||
plugins_available = {
|
||||
p.module: p for p in self.available_plugins(self.object)
|
||||
p.module: p for p in available_plugins(self.object)
|
||||
}
|
||||
choose_events_next = False
|
||||
with transaction.atomic():
|
||||
@@ -786,12 +787,6 @@ class OrganizerPluginEvents(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
}
|
||||
return kwargs
|
||||
|
||||
def available_plugins(self, organizer):
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
|
||||
return (p for p in get_all_plugins(organizer=organizer) if not p.name.startswith('.')
|
||||
and getattr(p, 'visible', True))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return super().get_context_data(
|
||||
plugin=self.plugin,
|
||||
@@ -799,12 +794,10 @@ class OrganizerPluginEvents(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
plugins_available = {
|
||||
p.module: p for p in self.available_plugins(self.request.organizer)
|
||||
}
|
||||
if kwargs["plugin"] not in plugins_available:
|
||||
try:
|
||||
self.plugin = next(p for p in available_plugins(self.request.organizer) if p.module == kwargs["plugin"])
|
||||
except StopIteration:
|
||||
raise Http404(_("Unknown plugin."))
|
||||
self.plugin = plugins_available[kwargs["plugin"]]
|
||||
level = getattr(self.plugin, "level", PLUGIN_LEVEL_EVENT)
|
||||
if level == PLUGIN_LEVEL_ORGANIZER:
|
||||
raise Http404(_("This plugin can only be enabled for the entire organizer account."))
|
||||
@@ -835,6 +828,9 @@ class OrganizerPluginEvents(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
logentries_to_save = []
|
||||
|
||||
for e in self.request.organizer.events.filter(pk__in=events_to_enable):
|
||||
if not plugin_is_available(self.plugin, organizer=self.request.organizer, event=e):
|
||||
messages.warning(self.request, _("This plugin cannot be activated for event {}.").format(e.name))
|
||||
continue
|
||||
logentries_to_save.append(
|
||||
e.log_action('pretix.event.plugins.enabled', user=self.request.user, data={'plugin': self.plugin.module}, save=False)
|
||||
)
|
||||
|
||||
@@ -117,12 +117,17 @@ class GroupConcat(Aggregate):
|
||||
template = "%(function)s(%(distinct)s%(field)s::text, '%(separator)s' ORDER BY %(field)s::text ASC)"
|
||||
else:
|
||||
template = "%(function)s(%(distinct)s%(field)s::text, '%(separator)s')"
|
||||
return super().as_sql(
|
||||
|
||||
template, params = super().as_sql(
|
||||
compiler, connection,
|
||||
function='string_agg',
|
||||
template=template,
|
||||
**extra_context,
|
||||
)
|
||||
if self.ordered:
|
||||
# ordered statement requires field parameters twice
|
||||
params = params + params
|
||||
return template, params
|
||||
|
||||
|
||||
class ReplicaRouter:
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2025-09-29 07:39+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"PO-Revision-Date: 2026-04-30 18:00+0000\n"
|
||||
"Last-Translator: Paul Berschick <paul@plainschwarz.com>\n"
|
||||
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"ca/>\n"
|
||||
"Language: ca\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.3\n"
|
||||
"X-Generator: Weblate 5.17\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -14132,13 +14132,13 @@ msgid "Contact:"
|
||||
msgstr "Adreça de contacte"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:54
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "You are receiving this email because you placed an order for {event}."
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You are receiving this email because you placed an order for "
|
||||
"<strong>%(event)s</strong>."
|
||||
msgstr "Heu rebut aquest correu perquè heu fet una comanda per {event}."
|
||||
msgstr ""
|
||||
"Has rebut aquest correu perquè has fet una inscripció a <strong>%(event)s</"
|
||||
"strong>."
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:93
|
||||
#: pretix/control/templates/pretixcontrol/organizers/customer.html:23
|
||||
@@ -24790,7 +24790,7 @@ msgstr "Data d'inici de l'esdeveniment"
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:465
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:55
|
||||
msgid "Voucher code used:"
|
||||
msgstr ""
|
||||
msgstr "Codi de descompte utilitzat:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:467
|
||||
#, fuzzy, python-format
|
||||
@@ -35206,11 +35206,9 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/forms/renderers.py:66
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_voucher_form.html:14
|
||||
#, fuzzy
|
||||
#| msgid "expired"
|
||||
msgctxt "form"
|
||||
msgid "required"
|
||||
msgstr "expirat"
|
||||
msgstr "obligatori"
|
||||
|
||||
#: pretix/presale/ical.py:87 pretix/presale/ical.py:146
|
||||
#: pretix/presale/ical.py:182
|
||||
@@ -35399,10 +35397,8 @@ msgid "We're now trying to book these add-ons for you!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:28
|
||||
#, fuzzy
|
||||
#| msgid "Meta information"
|
||||
msgid "Additional options for"
|
||||
msgstr "Informació meta"
|
||||
msgstr "Opcions addicionals per a"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:60
|
||||
#, fuzzy
|
||||
@@ -35754,12 +35750,11 @@ msgstr[0] "Heu de triar només una opció d'aquesta categoria."
|
||||
msgstr[1] "Heu de triar %(min_count)s d'aquesta categoria."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid "You can choose up to %(max_count)s options from this category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] "Podeu triar fins a %(max_count)s opcions d'aquesta categoria."
|
||||
msgstr[1] "Podeu triar fins a %(max_count)s opcions d'aquesta categoria."
|
||||
msgstr[0] "Pots triar una opció d'aquesta categoria."
|
||||
msgstr[1] "Pots escollir fins a %(max_count)s opcions d’aquesta categoria."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:34
|
||||
#, python-format
|
||||
|
||||
@@ -4,10 +4,10 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-04-23 17:00+0000\n"
|
||||
"Last-Translator: Nikolai <nikolai@lengefeldt.de>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/da/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2026-05-04 14:19+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"da/>\n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -36278,9 +36278,8 @@ msgstr "Fortsæt"
|
||||
#: pretix/presale/templates/pretixpresale/fragment_event_list_status.html:14
|
||||
#: pretix/presale/templates/pretixpresale/fragment_week_calendar.html:58
|
||||
#: pretix/presale/views/widget.py:441
|
||||
#, fuzzy
|
||||
msgid "Few tickets left"
|
||||
msgstr "PDF-billet"
|
||||
msgstr "Få billetter tilbage"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/fragment_calendar.html:92
|
||||
#: pretix/presale/templates/pretixpresale/fragment_day_calendar.html:97
|
||||
|
||||
@@ -5,8 +5,8 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-04-28 09:22+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"PO-Revision-Date: 2026-05-06 00:00+0000\n"
|
||||
"Last-Translator: Daniel Musketa <daniel@musketa.de>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"de/>\n"
|
||||
"Language: de\n"
|
||||
@@ -14,7 +14,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.17\n"
|
||||
"X-Generator: Weblate 5.17.1\n"
|
||||
"X-Poedit-Bookmarks: -1,-1,904,-1,-1,-1,-1,-1,-1,-1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
@@ -3072,7 +3072,7 @@ msgstr "Wertgutscheine"
|
||||
#: pretix/base/exporters/orderlist.py:1367
|
||||
msgid "Download a spreadsheet of all gift cards including their current value."
|
||||
msgstr ""
|
||||
"Tabelle (Excel oder CSV) mit allen Wertgutscheinen und deren aktuellen Wert."
|
||||
"Tabelle (Excel oder CSV) mit allen Wertgutscheinen und deren aktuellem Wert."
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:1378
|
||||
msgid "Show value at"
|
||||
@@ -4971,7 +4971,7 @@ msgstr ""
|
||||
"Sollte kurz sein und darf nur Kleinbuchstaben, Zahlen, Bindestriche und "
|
||||
"Punkte enthalten. Muss unter Ihren Veranstaltungen einmalig sein. Wir "
|
||||
"empfehlen eine Abkürzung oder ein Datum mit unter 10 Zeichen, das man sich "
|
||||
"gut merken kann. Sie können jedoch auch einen zufälligen Wert verwendet. "
|
||||
"gut merken kann. Sie können jedoch auch einen zufälligen Wert verwenden. "
|
||||
"Dies wird z.B. in Links, Bestellnummern, Rechnungsnummern und "
|
||||
"Verwendungszwecken für Banküberweisungen benutzt."
|
||||
|
||||
@@ -7515,7 +7515,7 @@ msgid ""
|
||||
"You are already on this waiting list! We will notify you as soon as we have "
|
||||
"a ticket available for you."
|
||||
msgstr ""
|
||||
"Sie sind bereits auf der Warteliste! Wir benachrichtigen Sie sobald wir ein "
|
||||
"Sie sind bereits auf der Warteliste! Wir benachrichtigen Sie, sobald wir ein "
|
||||
"verfügbares Ticket für Sie haben."
|
||||
|
||||
#: pretix/base/notifications.py:192 pretix/control/navigation.py:205
|
||||
@@ -8671,8 +8671,8 @@ msgid ""
|
||||
"offline scanning – please refer to documentation or support for details)"
|
||||
msgstr ""
|
||||
"pretix Signaturverfahren 1 (für sehr große Veranstaltungen, ändert die "
|
||||
"Funktionsweise des Offline-Modus, bitte informiere dich in der Dokumentation "
|
||||
"oder beim Support)"
|
||||
"Funktionsweise des Offline-Modus, bitte informieren Sie sich in der "
|
||||
"Dokumentation oder beim Support)"
|
||||
|
||||
#: pretix/base/services/cancelevent.py:265
|
||||
#: pretix/base/services/cancelevent.py:351
|
||||
@@ -9579,8 +9579,8 @@ msgid ""
|
||||
"changes are still accurate and try again."
|
||||
msgstr ""
|
||||
"Diese Bestellung wurde zeitgleich von einem anderen Benutzer bearbeitet. "
|
||||
"Bitte prüfe, ob deine Änderungen immer noch zutreffend sind und probiere es "
|
||||
"erneut."
|
||||
"Bitte prüfen Sie, ob Ihre Änderungen immer noch zutreffend sind und "
|
||||
"probieren Sie es erneut."
|
||||
|
||||
#: pretix/base/services/orders.py:150
|
||||
msgid "Your cart is empty."
|
||||
@@ -11363,7 +11363,7 @@ msgid ""
|
||||
"If your event series has more than 50 dates in the future, only the month or "
|
||||
"week calendar can be used."
|
||||
msgstr ""
|
||||
"Wenn deine Veranstaltungsreihe mehr als 50 zukünftige Termine hat, kann nur "
|
||||
"Wenn Ihre Veranstaltungsreihe mehr als 50 zukünftige Termine hat, kann nur "
|
||||
"der Monats- oder Wochenkalender verwendet werden."
|
||||
|
||||
#: pretix/base/settings.py:1892
|
||||
@@ -11636,8 +11636,9 @@ msgid ""
|
||||
"set this to e.g. 10, they will only be able to choose values in increments "
|
||||
"of 10."
|
||||
msgstr ""
|
||||
"Standardmäßig können Kunden auf einen beliebigen Betrag verzichten. Wenn du "
|
||||
"diesen Wert z.B. auf 10 setzt, sind nur noch Werte im Abstand von 10 erlaubt."
|
||||
"Standardmäßig können Kunden auf einen beliebigen Betrag verzichten. Wenn Sie "
|
||||
"diesen Wert z.B. auf 10 setzen, sind nur noch Werte im Abstand von 10 "
|
||||
"erlaubt."
|
||||
|
||||
#: pretix/base/settings.py:2193
|
||||
msgid ""
|
||||
@@ -17304,7 +17305,7 @@ msgstr ""
|
||||
|
||||
#: pretix/control/forms/vouchers.py:448
|
||||
msgid "You need to specify as many seats as voucher codes."
|
||||
msgstr "Sie müssen genau so viele Sitze angeben, wie du Gutscheine erzeugst."
|
||||
msgstr "Sie müssen genau so viele Sitze angeben, wie Sie Gutscheine erzeugen."
|
||||
|
||||
#: pretix/control/forms/waitinglist.py:39
|
||||
msgid "Select a valid choice."
|
||||
@@ -20819,7 +20820,7 @@ msgid ""
|
||||
"event and only retain the financial information such as the number and type "
|
||||
"of tickets sold."
|
||||
msgstr ""
|
||||
"Sie können personenbezogene Daten wie Namen und E-Mail-Adressen aus deiner "
|
||||
"Sie können personenbezogene Daten wie Namen und E-Mail-Adressen aus Ihrer "
|
||||
"Veranstaltung entfernen und nur finanzielle Infos wie die Anzahl und Art der "
|
||||
"verkauften Tickets aufbewahren."
|
||||
|
||||
@@ -23019,7 +23020,7 @@ msgstr ""
|
||||
"Wenn Sie eine Gültigkeit in Tagen, Monaten oder Jahren angeben, endet die "
|
||||
"Gültigkeit immer am Ende eines vollen Tages (Mitternacht), plus der "
|
||||
"ausgewählten Anzahl an Minuten und Stunden. Der Starttermin wird in die "
|
||||
"Berechnung eingeschlossen, d.h. wenn Sie \"1 Tag\" auswählen ist das Ticket "
|
||||
"Berechnung eingeschlossen, d.h. wenn Sie \"1 Tag\" auswählen, ist das Ticket "
|
||||
"gültig bis zum Ende des Tages, an dem die Gültigkeit beginnt."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/item/index.html:254
|
||||
@@ -23452,7 +23453,7 @@ msgid ""
|
||||
"statistical data on customers who previously selected this option, and when "
|
||||
"such customers edit their answers, they need to select a different option."
|
||||
msgstr ""
|
||||
"Wenn du eine Antwortoption löschst, kannst du anschließend keine "
|
||||
"Wenn Sie eine Antwortoption löschen, können Sie anschließend keine "
|
||||
"statistischen Daten mehr zur Verwendung dieser Option abrufen und wenn "
|
||||
"Kunden, die diese Option gewählt haben, ihre Daten bearbeiten möchten, muss "
|
||||
"eine andere Option gewählt werden."
|
||||
@@ -25961,8 +25962,8 @@ msgid ""
|
||||
"Instead of an URL, you can also configure a text that will be shown within "
|
||||
"pretix. This will be ignored if a URL is configured."
|
||||
msgstr ""
|
||||
"Statt einer URL kannst du auch einen Text eingeben, der von pretix angezeigt "
|
||||
"wird. Dies wird ignoriert, wenn eine URL konfiguriert wurde."
|
||||
"Statt einer URL können Sie auch einen Text eingeben, der von pretix "
|
||||
"angezeigt wird. Dies wird ignoriert, wenn eine URL konfiguriert wurde."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/edit.html:229
|
||||
msgid "Barcode media"
|
||||
@@ -26128,7 +26129,7 @@ msgid ""
|
||||
"This feature allows you to configure acceptance of gift cards across "
|
||||
"multiple organizer accounts."
|
||||
msgstr ""
|
||||
"Diese Funktion erlaubt dir, die Akzeptanz von Wertgutscheinen über mehrere "
|
||||
"Diese Funktion erlaubt Ihnen, die Akzeptanz von Wertgutscheinen über mehrere "
|
||||
"Veranstalterkonten hinweg zu konfigurieren."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/giftcard_acceptance_list.html:18
|
||||
@@ -26168,7 +26169,7 @@ msgstr "Ablehnen"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/giftcard_acceptance_list.html:84
|
||||
msgid "Other organizers accepting gift cards from you"
|
||||
msgstr "Andere Veranstalter, die deine Wertgutscheine akzeptieren"
|
||||
msgstr "Andere Veranstalter, die Ihre Wertgutscheine akzeptieren"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/giftcard_acceptance_list.html:87
|
||||
msgid ""
|
||||
@@ -27156,9 +27157,9 @@ msgid ""
|
||||
"use pretixPRINT version %(print_version)s (or newer) or pretixSCAN Desktop "
|
||||
"version %(scan_version)s (or newer)."
|
||||
msgstr ""
|
||||
"Dieses Layout verwendet neue Funktionen. Wenn du mit einem Gerät druckst, "
|
||||
"stelle sicher, dass pretixPRINT-Version %(print_version)s (oder neuer) oder "
|
||||
"pretixSCAN Desktop Version %(scan_version)s (oder neuer) im Einsatz ist."
|
||||
"Dieses Layout verwendet neue Funktionen. Wenn Sie mit einem Gerät drucken, "
|
||||
"stellen Sie sicher, dass pretixPRINT-Version %(print_version)s (oder neuer) "
|
||||
"oder pretixSCAN Desktop Version %(scan_version)s (oder neuer) im Einsatz ist."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/placeholders.html:16
|
||||
msgid "Available placeholders"
|
||||
@@ -27234,8 +27235,8 @@ msgid ""
|
||||
"might be required to keep some of this data on file. You can therefore "
|
||||
"download the following file and store it in a safe place:"
|
||||
msgstr ""
|
||||
"Sie sind dabei, Daten unwiderruflich vom Server zu löschen, auch wenn du "
|
||||
"manche dieser Daten ggf. aus gesetzlichen Gründen noch aufheben musst. Wir "
|
||||
"Sie sind dabei, Daten unwiderruflich vom Server zu löschen, auch wenn Sie "
|
||||
"manche dieser Daten ggf. aus gesetzlichen Gründen noch aufheben müssen. Wir "
|
||||
"empfehlen daher, die folgende Datei herunterzuladen und sie sicher "
|
||||
"aufzubewahren:"
|
||||
|
||||
@@ -27284,7 +27285,7 @@ msgid ""
|
||||
"while to complete. We will inform you via email once it has been completed."
|
||||
msgstr ""
|
||||
"Abhängig von der Datenmenge in der Veranstaltung kann der folgende Schritt "
|
||||
"eine Weile dauern. Wir informieren dich per E-Mail, sobald er abgeschlossen "
|
||||
"eine Weile dauern. Wir informieren Sie per E-Mail, sobald er abgeschlossen "
|
||||
"ist."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/shredder/index.html:11
|
||||
@@ -32188,8 +32189,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Während die meisten Zahlungsmethoden keinen grundlosen Widerruf vorsehen, "
|
||||
"können SEPA-Lastschriften per Mausklick zurückgerufen werden. Aus diesem "
|
||||
"Grund - und abhängig von der Art Ihrer Veranstaltung - kann es notwendig "
|
||||
"sein SEPA-Lastschriften nicht anzubieten und damit das Risiko von "
|
||||
"Grund – und abhängig von der Art Ihrer Veranstaltung – kann es notwendig "
|
||||
"sein, SEPA-Lastschriften nicht anzubieten und damit das Risiko von "
|
||||
"kostspieligen Rücklastschriften zu vermeiden."
|
||||
|
||||
#: pretix/plugins/paypal2/payment.py:182
|
||||
@@ -33624,8 +33625,8 @@ msgid ""
|
||||
"Some payment methods might need to be enabled in the settings of your Stripe "
|
||||
"account before they work properly."
|
||||
msgstr ""
|
||||
"Manche Zahlungsmethoden müssen in den Einstellungen deines Stripe-Kontos "
|
||||
"aktiviert werden bevor sie funktionieren."
|
||||
"Manche Zahlungsmethoden müssen in den Einstellungen Ihres Stripe-Kontos "
|
||||
"aktiviert werden, bevor sie funktionieren."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:369 pretix/plugins/stripe/payment.py:1597
|
||||
msgid "Alipay"
|
||||
@@ -33644,8 +33645,8 @@ msgid ""
|
||||
"Some payment methods might need to be enabled in the settings of your Stripe "
|
||||
"account before work properly."
|
||||
msgstr ""
|
||||
"Manche Zahlungsmethoden müssen in den Einstellungen deines Stripe-Kontos "
|
||||
"aktiviert werden bevor sie funktionieren."
|
||||
"Manche Zahlungsmethoden müssen in den Einstellungen Ihres Stripe-Kontos "
|
||||
"aktiviert werden, bevor sie funktionieren."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:391
|
||||
msgid ""
|
||||
@@ -35338,7 +35339,7 @@ msgstr "Diese Zahlungsmethode unterstützt den Testmodus nicht."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_payment.html:113
|
||||
msgid "If you continue, actual money might be transferred."
|
||||
msgstr "Wenn du fortfährst, wird möglicherweise echtes Geld transferiert."
|
||||
msgstr "Wenn Sie fortfahren, wird möglicherweise echtes Geld transferiert."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_payment.html:124
|
||||
msgid "There are no payment providers enabled."
|
||||
@@ -35790,7 +35791,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Da Sie eine Firmenadresse eingegeben haben, wurde Ihr Preis aus dem Preis "
|
||||
"ohne Umsatzsteuer neu berechnet. Durch geänderte Rundung hat sich der "
|
||||
"Endpreis deiner Buchung minimal verändert."
|
||||
"Endpreis Ihrer Buchung minimal verändert."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:516
|
||||
#, python-format
|
||||
@@ -36025,7 +36026,7 @@ msgid ""
|
||||
"the order clicked the link in the email they received to confirm the email "
|
||||
"address is valid."
|
||||
msgstr ""
|
||||
"Sie können Ihre Tickets hier herunterladen sobald die Person, die die "
|
||||
"Sie können Ihre Tickets hier herunterladen, sobald die Person, die die "
|
||||
"Bestellung aufgegeben hat, einen Link in der an sie geschickten E-Mail "
|
||||
"geklickt hat."
|
||||
|
||||
@@ -37011,10 +37012,10 @@ msgid ""
|
||||
"need the ticket any more, please be so kind and remove your ticket from the "
|
||||
"list so we can pass it on to the next person waiting as quickly as possible!"
|
||||
msgstr ""
|
||||
"Sie wurden von unserer Warteliste ausgewählt um ein Ticket zu erhalten. Wenn "
|
||||
"Sie das Ticket nicht mehr brauchen, helfen Sie uns indem Sie sich von der "
|
||||
"Warteliste entfernen, sodass wir das Ticket schnellstmöglich an die nächste "
|
||||
"wartende Person weitergeben können."
|
||||
"Sie wurden von unserer Warteliste ausgewählt, um ein Ticket zu erhalten. "
|
||||
"Wenn Sie das Ticket nicht mehr brauchen, helfen Sie uns, indem Sie sich von "
|
||||
"der Warteliste entfernen, sodass wir das Ticket schnellstmöglich an die "
|
||||
"nächste wartende Person weitergeben können."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/waitinglist_remove.html:16
|
||||
msgctxt "waitinglist"
|
||||
@@ -37754,8 +37755,8 @@ msgstr ""
|
||||
#: pretix/presale/views/order.py:1198
|
||||
msgid "Please click the link we sent you via email to download your tickets."
|
||||
msgstr ""
|
||||
"Bitte klicke den Link, den wir dir per E-Mail geschickt haben, um deine "
|
||||
"Tickets herunterzuladen."
|
||||
"Bitte klicken Sie den Link, den wir Ihnen per E-Mail geschickt haben, um "
|
||||
"Ihre Tickets herunterzuladen."
|
||||
|
||||
#: pretix/presale/views/order.py:1689
|
||||
#, python-brace-format
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-04-28 09:22+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"PO-Revision-Date: 2026-05-04 10:44+0000\n"
|
||||
"Last-Translator: Daniel Musketa <daniel@musketa.de>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix/de_Informal/>\n"
|
||||
"Language: de_Informal\n"
|
||||
@@ -829,7 +829,7 @@ msgid ""
|
||||
"Field \"{field_name}\" requires {required_input}, but only got "
|
||||
"{available_inputs}. Please check your {provider_name} settings."
|
||||
msgstr ""
|
||||
"Feld \"{field_name}\" erfordert {required_input}, aber hat nur "
|
||||
"Feld \"{field_name}\" erfordert {required_input}, aber nur "
|
||||
"{available_inputs} sind verfügbar. Bitte prüfe die Einstellungen für "
|
||||
"{provider_name}."
|
||||
|
||||
@@ -1529,8 +1529,8 @@ msgid ""
|
||||
"Only include invoices issued in this time frame. Note that the invoice date "
|
||||
"does not always correspond to the order or payment date."
|
||||
msgstr ""
|
||||
"Nur Rechnungen, die in diesem Zeitraum wurden. Achtung: Das Rechnungsdatum "
|
||||
"korrespondiert nicht zwingend zum Bestell- oder Zahlungsdatum."
|
||||
"Nur Rechnungen, die in diesem Zeitraum ausgestellt wurden. Achtung: Das "
|
||||
"Rechnungsdatum korrespondiert nicht zwingend zum Bestell- oder Zahlungsdatum."
|
||||
|
||||
#: pretix/base/exporters/events.py:47
|
||||
msgid "Event data"
|
||||
@@ -3540,7 +3540,7 @@ msgstr "Das eingegebene aktuelle Passwort war nicht korrekt."
|
||||
|
||||
#: pretix/base/forms/user.py:95
|
||||
msgid "Please choose a password different to your current one."
|
||||
msgstr "Bitte wählen ein anderes Passwort als das derzeitige."
|
||||
msgstr "Bitte wähle ein anderes Passwort als das derzeitige."
|
||||
|
||||
#: pretix/base/forms/user.py:105 pretix/presale/forms/customer.py:399
|
||||
#: pretix/presale/forms/customer.py:475
|
||||
@@ -3579,7 +3579,7 @@ msgid ""
|
||||
"up. Please note: to use literal \"{\" or \"}\", you need to double them as "
|
||||
"\"{{\" and \"}}\"."
|
||||
msgstr ""
|
||||
"Es ist ein Fehler in deine Platzhalter-Syntax. Bitte prüfe, dass die "
|
||||
"Es ist ein Fehler in deiner Platzhalter-Syntax. Bitte prüfe, dass die "
|
||||
"öffnenden \"{\" und schließenden \"}\" geschweiften Klammern zusammenpassen. "
|
||||
"Um die geschweiften Klammern \"{\" und \"}\" im erzeugten Text zu verwenden, "
|
||||
"müssen sie doppelt gesetzt werden als \"{{\" und \"}}\"."
|
||||
@@ -4217,7 +4217,7 @@ msgstr "Automatisch generieren"
|
||||
|
||||
#: pretix/base/modelimport_orders.py:496
|
||||
msgid "You cannot assign a position secret that already exists."
|
||||
msgstr "Sie können keinen Ticketcode verwenden, der bereits existiert."
|
||||
msgstr "Du kannst keinen Ticketcode verwenden, der bereits existiert."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:528
|
||||
msgid "Please enter a valid language code."
|
||||
@@ -4971,7 +4971,7 @@ msgstr ""
|
||||
"Sollte kurz sein und darf nur Kleinbuchstaben, Zahlen, Bindestriche und "
|
||||
"Punkte enthalten. Muss unter deinen Veranstaltungen einmalig sein. Wir "
|
||||
"empfehlen eine Abkürzung oder ein Datum mit unter 10 Zeichen, das man sich "
|
||||
"gut merken kann. Du kannst jedoch auch einen zufälligen Wert verwendet. Dies "
|
||||
"gut merken kann. Du kannst jedoch auch einen zufälligen Wert verwenden. Dies "
|
||||
"wird z.B. in Links, Bestellnummern, Rechnungsnummern und Verwendungszwecken "
|
||||
"für Banküberweisungen benutzt."
|
||||
|
||||
@@ -6186,7 +6186,7 @@ msgstr "Minimaler Wert"
|
||||
#: pretix/base/models/items.py:1747 pretix/base/models/items.py:1750
|
||||
#: pretix/base/models/items.py:1754
|
||||
msgid "Currently not supported in our apps and during check-in"
|
||||
msgstr "Derzeit nicht von unseren Apps und während dem Check-In unterstützt"
|
||||
msgstr "Derzeit nicht von unseren Apps und beim Check-In unterstützt"
|
||||
|
||||
#: pretix/base/models/items.py:1737 pretix/base/models/items.py:1743
|
||||
#: pretix/base/models/items.py:1749
|
||||
@@ -6231,7 +6231,7 @@ msgstr "Ungültige Nummerneingabe."
|
||||
|
||||
#: pretix/base/models/items.py:1870 pretix/base/models/items.py:1894
|
||||
msgid "Please choose a later date."
|
||||
msgstr "Bitte wählen Sie ein späteres Datum."
|
||||
msgstr "Bitte wähle ein späteres Datum."
|
||||
|
||||
#: pretix/base/models/items.py:1872 pretix/base/models/items.py:1896
|
||||
msgid "Please choose an earlier date."
|
||||
@@ -6880,7 +6880,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Wenn du dies anschaltest, müssen alle Mitglieder entweder Zwei-Faktor-"
|
||||
"Authentifizierung einrichten oder das Team verlassen. Die Einstellung kann "
|
||||
"ein paar Minuten benötigen um für alle Benutzer aktiv zu werden."
|
||||
"ein paar Minuten benötigen, um für alle Benutzer aktiv zu werden."
|
||||
|
||||
#: pretix/base/models/organizer.py:384
|
||||
msgid "All event permissions"
|
||||
@@ -9015,7 +9015,7 @@ msgstr ""
|
||||
msgid "One of the products you selected can only be bought part of a bundle."
|
||||
msgstr ""
|
||||
"Eins der ausgewählten Produkte wird nicht einzeln verkauft, sondern nur als "
|
||||
"Teil fester Produktpaketen."
|
||||
"Teil fester Produktpakete."
|
||||
|
||||
#: pretix/base/services/cart.py:218
|
||||
msgid "Please select a valid seat."
|
||||
@@ -9912,7 +9912,7 @@ msgid ""
|
||||
"country is currently not available. We will therefore need to charge you the "
|
||||
"same tax rate as if you did not enter a VAT ID."
|
||||
msgstr ""
|
||||
"Die USt-ID-Nr. konnte nicht geprüft werden, da der Prüfdienst Ihres Landes "
|
||||
"Die USt-ID-Nr. konnte nicht geprüft werden, da der Prüfdienst deines Landes "
|
||||
"im Moment nicht verfügbar ist. Wir müssen daher den selben Steuersatz "
|
||||
"berechnen, wie wenn keine USt-ID-Nr. eingegeben worden wäre."
|
||||
|
||||
@@ -11535,8 +11535,8 @@ msgid ""
|
||||
"cancellation fee from the user."
|
||||
msgstr ""
|
||||
"Betrifft nur ausstehende Zahlungen, für kostenlose Bestellungen wird nie "
|
||||
"eine Stornogebühr erhoben. Bitte beachten Sie, dass Sie für das Eintreiben "
|
||||
"der Stornogebühr selbst verantwortlich sind."
|
||||
"eine Stornogebühr erhoben. Bitte beachte, dass du für das Eintreiben der "
|
||||
"Stornogebühr selbst verantwortlich bist."
|
||||
|
||||
#: pretix/base/settings.py:2073
|
||||
msgid "Charge payment, shipping and service fees"
|
||||
@@ -19340,8 +19340,8 @@ msgstr ""
|
||||
msgid ""
|
||||
"Please leave a short comment on what you did in the following admin sessions:"
|
||||
msgstr ""
|
||||
"Bitte hinterlassen Sie einen kurzen Kommentar, was Sie in diesen Admin-"
|
||||
"Sitzungen gemacht haben:"
|
||||
"Bitte hinterlasse einen kurzen Kommentar, was du in diesen Admin-Sitzungen "
|
||||
"gemacht hast:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/base.html:376
|
||||
msgid "Read more"
|
||||
@@ -19427,8 +19427,7 @@ msgstr "im Entwicklermodus"
|
||||
#: pretix/presale/templates/pretixpresale/postmessage.html:27
|
||||
#: pretix/presale/templates/pretixpresale/waiting.html:42
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr ""
|
||||
"Wenn dies länger als einige Minuten dauert, kontaktieren Sie uns bitte."
|
||||
msgstr "Wenn dies länger als einige Minuten dauert, kontaktiere uns bitte."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/boxoffice/payment.html:4
|
||||
#: pretix/control/templates/pretixcontrol/organizers/devices.html:75
|
||||
@@ -22988,7 +22987,7 @@ msgstr ""
|
||||
"Wenn du eine Gültigkeit in Tagen, Monaten oder Jahren angibst, endet die "
|
||||
"Gültigkeit immer am Ende eines vollen Tages (Mitternacht), plus der "
|
||||
"ausgewählten Anzahl an Minuten und Stunden. Der Starttermin wird in die "
|
||||
"Berechnung eingeschlossen, d.h. wenn Sie \"1 Tag\" auswählen ist das Ticket "
|
||||
"Berechnung eingeschlossen, d.h. wenn du \"1 Tag\" auswählst, ist das Ticket "
|
||||
"gültig bis zum Ende des Tages, an dem die Gültigkeit beginnt."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/item/index.html:254
|
||||
@@ -23662,8 +23661,8 @@ msgid ""
|
||||
"Are you sure you want to generate a new client secret for the application "
|
||||
"<strong>%(application)s</strong>?"
|
||||
msgstr ""
|
||||
"Möchten Sie wirklich einen neuen Schlüssel für die App "
|
||||
"<strong>%(application)s</strong> generieren?"
|
||||
"Möchtest du wirklich einen neuen Schlüssel für die App <strong>%(application)"
|
||||
"s</strong> generieren?"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/oauth/app_rollkeys.html:15
|
||||
msgid "Roll secret"
|
||||
@@ -23720,7 +23719,7 @@ msgstr "Bestellung freigeben"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/approve.html:10
|
||||
msgid "Do you really want to approve this order?"
|
||||
msgstr "Möchten Sie diese Bestellung wirklich freigeben?"
|
||||
msgstr "Möchtest du diese Bestellung wirklich freigeben?"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/approve.html:20
|
||||
#: pretix/control/templates/pretixcontrol/order/cancel.html:46
|
||||
@@ -25689,8 +25688,8 @@ msgid ""
|
||||
"Download an app that is compatible with pretix. For example, our check-in "
|
||||
"app <strong>pretixSCAN</strong> is available on all major platforms."
|
||||
msgstr ""
|
||||
"Laden Sie eine App herunter, die mit pretix kompatibel ist, wie z.B. unsere "
|
||||
"Check-in-App <strong>pretixSCAN</strong>."
|
||||
"Lade eine App herunter, die mit pretix kompatibel ist, wie z.B. unsere Check-"
|
||||
"in-App <strong>pretixSCAN</strong>."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/device_connect.html:14
|
||||
msgid "Download pretixSCAN"
|
||||
@@ -25917,7 +25916,7 @@ msgid ""
|
||||
"target=\"_blank\">our documentation</a>."
|
||||
msgstr ""
|
||||
"In einigen Regionen, einschließlich der Europäischen Union, bist du "
|
||||
"verpflichtet, Informationen über die Barrierefreiheit Ihres Ticketshops zu "
|
||||
"verpflichtet, Informationen über die Barrierefreiheit deines Ticketshops zu "
|
||||
"veröffentlichen. Du findest eine Vorlage in <a href=\"https://docs.pretix.eu/"
|
||||
"de/trust/accessibility/\" target=\"_blank\">unserer Dokumentation</a>."
|
||||
|
||||
@@ -26023,7 +26022,7 @@ msgstr "Station löschen:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/gate_delete.html:8
|
||||
msgid "Are you sure you want to delete the gate?"
|
||||
msgstr "Möchten Sie die Station wirklich löschen?"
|
||||
msgstr "Möchtest du die Station wirklich löschen?"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/gate_edit.html:6
|
||||
msgid "Gate:"
|
||||
@@ -26389,7 +26388,7 @@ msgid ""
|
||||
"The plugin \"%(name)s\" is enabled for your organizer account, but also "
|
||||
"needs to be enabled for the specific events you want to use it with."
|
||||
msgstr ""
|
||||
"Die Erweiterung \"%(name)s\" ist für Ihr Veranstalterkonto aktiv, muss "
|
||||
"Die Erweiterung \"%(name)s\" ist für dein Veranstalterkonto aktiv, muss "
|
||||
"jedoch auch für die einzelnen Veranstaltungen aktiviert werden, für die sie "
|
||||
"benutzt werden soll."
|
||||
|
||||
@@ -26936,7 +26935,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Dieser Editor wurde mit aktuellen Versionen von Google Chrome, Mozilla "
|
||||
"Firefox und Opera getestet. Andere Browser, besonders Internet Explorer oder "
|
||||
"Microsoft Edge, haben möglicherweise Probleme Ihr Hintergrund-PDF korrekt "
|
||||
"Microsoft Edge, haben möglicherweise Probleme, dein Hintergrund-PDF korrekt "
|
||||
"darzustellen oder die richtigen Schriftarten zu laden."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/index.html:207
|
||||
@@ -27121,9 +27120,9 @@ msgid ""
|
||||
"use pretixPRINT version %(print_version)s (or newer) or pretixSCAN Desktop "
|
||||
"version %(scan_version)s (or newer)."
|
||||
msgstr ""
|
||||
"Dieses Layout verwendet neue Funktionen. Wenn Sie mit einem Gerät drucken, "
|
||||
"stellen Sie sicher, dass pretixPRINT-Version %(print_version)s (oder neuer) "
|
||||
"oder pretixSCAN Desktop Version %(scan_version)s (oder neuer) im Einsatz ist."
|
||||
"Dieses Layout verwendet neue Funktionen. Wenn du mit einem Gerät druckst, "
|
||||
"stell sicher, dass pretixPRINT-Version %(print_version)s (oder neuer) oder "
|
||||
"pretixSCAN Desktop Version %(scan_version)s (oder neuer) im Einsatz ist."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/placeholders.html:16
|
||||
msgid "Available placeholders"
|
||||
@@ -27397,7 +27396,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Du kannst entweder eine oder mehrere Check-in-Listen für jeden Termin deiner "
|
||||
"Veranstaltungsreihe einzeln anlegen oder nur eine Check-in-Liste für alle "
|
||||
"Ihre Termine verwenden und den Einlass über Check-in-Regeln limitieren. "
|
||||
"deine Termine verwenden und den Einlass über Check-in-Regeln limitieren. "
|
||||
"Welcher Ansatz besser geeignet ist, hängt von mehreren Faktoren ab, wie z.B. "
|
||||
"der Menge an Terminen in deiner Veranstaltungsreihe. Für Reihen mit weniger "
|
||||
"als einem Termin pro Tag sind einzelne Check-in-Listen in der Regel "
|
||||
@@ -29233,7 +29232,7 @@ msgid ""
|
||||
"participants won't be able to buy the bundle unless you remove this item "
|
||||
"from it."
|
||||
msgstr ""
|
||||
"Sie haben dieses Produkt deaktiviert, obwohl es Teil eines Paketes ist. "
|
||||
"Du hast dieses Produkt deaktiviert, obwohl es Teil eines Paketes ist. "
|
||||
"Solange dies so ist, kann auch das Paket nicht mehr gekauft werden."
|
||||
|
||||
#: pretix/control/views/item.py:1622
|
||||
@@ -30396,7 +30395,7 @@ msgid ""
|
||||
"and requested a reset of the credentials."
|
||||
msgstr ""
|
||||
"Ein Zwei-Faktor-Notfall-Token wurde von einem Systemadministrator generiert. "
|
||||
"Dies passiert üblicherweise, wenn du den Zugriff auf Ihren zweiten Faktor "
|
||||
"Dies passiert üblicherweise, wenn du den Zugriff auf deinen zweiten Faktor "
|
||||
"verloren und ein Zurücksetzen der Zugangsdaten angefordert hast."
|
||||
|
||||
#: pretix/control/views/users.py:169
|
||||
@@ -32143,8 +32142,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Während die meisten Zahlungsmethoden keinen grundlosen Widerruf vorsehen, "
|
||||
"können SEPA-Lastschriften per Mausklick zurückgerufen werden. Aus diesem "
|
||||
"Grund - und abhängig von der Art Ihrer Veranstaltung - kann es notwendig "
|
||||
"sein SEPA-Lastschriften nicht anzubieten und damit das Risiko von "
|
||||
"Grund – und abhängig von der Art deiner Veranstaltung – kann es notwendig "
|
||||
"sein, SEPA-Lastschriften nicht anzubieten und damit das Risiko von "
|
||||
"kostspieligen Rücklastschriften zu vermeiden."
|
||||
|
||||
#: pretix/plugins/paypal2/payment.py:182
|
||||
@@ -32474,7 +32473,7 @@ msgid ""
|
||||
"Your PayPal account is now connected to pretix. You can change the settings "
|
||||
"in detail below."
|
||||
msgstr ""
|
||||
"Ihr PayPal-Konto ist nun mit pretix verbunden. Auf dieser Seite können Sie "
|
||||
"Dein PayPal-Konto ist nun mit pretix verbunden. Auf dieser Seite kannst du "
|
||||
"die Einstellungen im Detail anpassen."
|
||||
|
||||
#: pretix/plugins/pretixdroid/apps.py:30 pretix/plugins/pretixdroid/apps.py:33
|
||||
@@ -33051,7 +33050,8 @@ msgstr "Neue Regel erstellen"
|
||||
#: pretix/plugins/sendmail/templates/pretixplugins/sendmail/rule_update.html:10
|
||||
msgid "Scheduled emails are not sent as long as your ticket shop is offline."
|
||||
msgstr ""
|
||||
"Geplante E-Mails werden nicht verschickt, solange Ihr Ticketshop offline ist."
|
||||
"Geplante E-Mails werden nicht verschickt, solange dein Ticketshop offline "
|
||||
"ist."
|
||||
|
||||
#: pretix/plugins/sendmail/templates/pretixplugins/sendmail/rule_create.html:49
|
||||
#: pretix/plugins/sendmail/templates/pretixplugins/sendmail/rule_update.html:63
|
||||
@@ -33383,7 +33383,7 @@ msgid ""
|
||||
"methods such as iDEAL, Alipay,and many more."
|
||||
msgstr ""
|
||||
"Akzeptiere Zahlungen über Stripe, einen weltweit beliebten "
|
||||
"Zahlungsdienstleister. PayPal unterstützt Zahlungen per Kreditkarte sowie "
|
||||
"Zahlungsdienstleister. Stripe unterstützt Zahlungen per Kreditkarte sowie "
|
||||
"viele lokale Zahlungsarten wie z.B. iDEAL, Alipay, und viele mehr."
|
||||
|
||||
#: pretix/plugins/stripe/forms.py:40
|
||||
@@ -33968,8 +33968,8 @@ msgid ""
|
||||
"Pay by bank allows you to authorize a secure Open Banking payment from your "
|
||||
"banking app. Currently available only with a UK bank account."
|
||||
msgstr ""
|
||||
"Zahlung per Onlinebanking erlaubt die sichere Zahlung über Ihre Banking-App. "
|
||||
"Derzeit nur für britische Bankkonten verfügbar."
|
||||
"Zahlung per Onlinebanking erlaubt die sichere Zahlung über deine Banking-"
|
||||
"App. Derzeit nur für britische Bankkonten verfügbar."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1886
|
||||
msgid "PayPal via Stripe"
|
||||
@@ -34356,7 +34356,7 @@ msgid ""
|
||||
"Your Stripe account is now connected to pretix. You can change the settings "
|
||||
"in detail below."
|
||||
msgstr ""
|
||||
"Ihr Stripe-Konto ist nun mit pretix verbunden. Auf dieser Seite können Sie "
|
||||
"Dein Stripe-Konto ist nun mit pretix verbunden. Auf dieser Seite kannst du "
|
||||
"die Einstellungen im Detail anpassen."
|
||||
|
||||
#: pretix/plugins/stripe/views.py:488
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:04+0000\n"
|
||||
"PO-Revision-Date: 2026-03-17 14:30+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"PO-Revision-Date: 2026-05-04 07:42+0000\n"
|
||||
"Last-Translator: Martin Gross <gross@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix-js/de_Informal/>\n"
|
||||
"Language: de_Informal\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.16.2\n"
|
||||
"X-Generator: Weblate 5.17\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -428,8 +428,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr ""
|
||||
"Wenn dies länger als einige Minuten dauert, kontaktieren Sie uns bitte."
|
||||
msgstr "Wenn dies länger als einige Minuten dauert, kontaktiere uns bitte."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
||||
msgid "Close message"
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-04-17 03:00+0000\n"
|
||||
"Last-Translator: Tim <plicnetwork@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-05-01 21:00+0000\n"
|
||||
"Last-Translator: Paul Berschick <paul@plainschwarz.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"es/>\n"
|
||||
"Language: es\n"
|
||||
@@ -8231,10 +8231,8 @@ msgstr ""
|
||||
"2x complemento 2"
|
||||
|
||||
#: pretix/base/pdf.py:383
|
||||
#, fuzzy
|
||||
#| msgid "List of Add-Ons"
|
||||
msgid "List of Checked-In Add-Ons"
|
||||
msgstr "Lista de add-ons"
|
||||
msgstr "Lista de complementos registrados"
|
||||
|
||||
#: pretix/base/pdf.py:390 pretix/control/forms/filter.py:1537
|
||||
#: pretix/control/forms/filter.py:1539
|
||||
@@ -9237,10 +9235,8 @@ msgid "Czech National Bank"
|
||||
msgstr "Banco Nacional Checo"
|
||||
|
||||
#: pretix/base/services/currencies.py:41
|
||||
#, fuzzy
|
||||
#| msgid "Czech National Bank"
|
||||
msgid "National Bank of Poland"
|
||||
msgstr "Banco Nacional Checo"
|
||||
msgstr "Banco Nacional de Polonia"
|
||||
|
||||
#: pretix/base/services/export.py:95 pretix/base/services/export.py:155
|
||||
msgid ""
|
||||
@@ -10336,16 +10332,12 @@ msgstr ""
|
||||
"importe de la factura no esté en CZK."
|
||||
|
||||
#: pretix/base/settings.py:577 pretix/base/settings.py:586
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Based on Czech National Bank daily rates, whenever the invoice amount is "
|
||||
#| "not in CZK."
|
||||
msgid ""
|
||||
"Based on National Bank of Poland daily rates, whenever the invoice amount is "
|
||||
"not in PLN."
|
||||
msgstr ""
|
||||
"Basado en las tarifas diarias del Banco Nacional Checo, siempre que el "
|
||||
"importe de la factura no esté en CZK."
|
||||
"Según los tipos de cambio diarios del Banco Nacional de Polonia, siempre que "
|
||||
"el importe de la factura no esté en PLN."
|
||||
|
||||
#: pretix/base/settings.py:597
|
||||
msgid "Require invoice address"
|
||||
@@ -16430,10 +16422,8 @@ msgid "Allow to overbook quotas when performing this operation"
|
||||
msgstr "Permitir sobrevender cupos cuando se realice esta operación"
|
||||
|
||||
#: pretix/control/forms/orders.py:335
|
||||
#, fuzzy
|
||||
#| msgid "Number of orders"
|
||||
msgid "Number of products to add"
|
||||
msgstr "Número de pedidos"
|
||||
msgstr "Número de productos que se van a añadir"
|
||||
|
||||
#: pretix/control/forms/orders.py:344
|
||||
msgid "Add-on to"
|
||||
@@ -16465,10 +16455,8 @@ msgstr ""
|
||||
"defecto del producto"
|
||||
|
||||
#: pretix/control/forms/orders.py:441
|
||||
#, fuzzy
|
||||
#| msgid "You can not select the same seat multiple times."
|
||||
msgid "You can not choose a seat when adding multiple products at once."
|
||||
msgstr "No se puede seleccionar la misma butaca varias veces."
|
||||
msgstr "No es posible elegir un asiento al añadir varios productos a la vez."
|
||||
|
||||
#: pretix/control/forms/orders.py:478 pretix/control/forms/orders.py:482
|
||||
#: pretix/control/forms/orders.py:510 pretix/control/forms/orders.py:552
|
||||
@@ -17076,7 +17064,7 @@ msgstr "Día de fin de semana"
|
||||
#: pretix/control/forms/subevents.py:106
|
||||
msgctxt "subevent"
|
||||
msgid "Skip dates that overlap with any existing date"
|
||||
msgstr ""
|
||||
msgstr "Omite las fechas que coincidan con alguna fecha ya existente"
|
||||
|
||||
#: pretix/control/forms/subevents.py:109
|
||||
msgctxt "subevent"
|
||||
@@ -17086,6 +17074,11 @@ msgid ""
|
||||
"This respects even inactive dates and works best if all dates have both a "
|
||||
"start and end time."
|
||||
msgstr ""
|
||||
"Esto puede resultar útil si todas tus citas tienen lugar en el mismo lugar y "
|
||||
"no se deben crear citas repetidas que entren en conflicto con eventos "
|
||||
"especiales ya existentes. Esta función tiene en cuenta incluso las citas "
|
||||
"inactivas y funciona mejor si todas las citas tienen una hora de inicio y "
|
||||
"una hora de finalización."
|
||||
|
||||
#: pretix/control/forms/subevents.py:128
|
||||
msgid "Keep the current values"
|
||||
@@ -24364,7 +24357,7 @@ msgstr "Escaneo de entrada: %(date)s"
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:465
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:55
|
||||
msgid "Voucher code used:"
|
||||
msgstr "Código de vale de compra utilizado:"
|
||||
msgstr "Código de descuento utilizado:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:467
|
||||
#, python-format
|
||||
@@ -30280,6 +30273,8 @@ msgstr "No cree más de 100.000 fechas a la vez."
|
||||
#: pretix/control/views/subevents.py:966
|
||||
msgid "All dates would be skipped because they conflict with existing dates."
|
||||
msgstr ""
|
||||
"Se omitirían todas las fechas, ya que entran en conflicto con las ya "
|
||||
"existentes."
|
||||
|
||||
#: pretix/control/views/subevents.py:1102
|
||||
#, python-brace-format
|
||||
@@ -34927,7 +34922,7 @@ msgstr "tiene errores"
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_voucher_form.html:14
|
||||
msgctxt "form"
|
||||
msgid "required"
|
||||
msgstr "requerido"
|
||||
msgstr "obligatorio"
|
||||
|
||||
#: pretix/presale/ical.py:87 pretix/presale/ical.py:146
|
||||
#: pretix/presale/ical.py:182
|
||||
|
||||
@@ -4,16 +4,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-03-31 17:00+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2026-05-08 04:00+0000\n"
|
||||
"Last-Translator: corentin-spec <corentin@spectentaculaire.fr>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"fr/>\n"
|
||||
"Language: fr\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.16.2\n"
|
||||
"X-Generator: Weblate 5.17.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -8279,10 +8279,8 @@ msgstr ""
|
||||
"2x Add-on 2"
|
||||
|
||||
#: pretix/base/pdf.py:383
|
||||
#, fuzzy
|
||||
#| msgid "List of Add-Ons"
|
||||
msgid "List of Checked-In Add-Ons"
|
||||
msgstr "Liste des Addons"
|
||||
msgstr "Liste des modules complémentaires enregistrés"
|
||||
|
||||
#: pretix/base/pdf.py:390 pretix/control/forms/filter.py:1537
|
||||
#: pretix/control/forms/filter.py:1539
|
||||
@@ -9296,10 +9294,8 @@ msgid "Czech National Bank"
|
||||
msgstr "Banque nationale tchèque"
|
||||
|
||||
#: pretix/base/services/currencies.py:41
|
||||
#, fuzzy
|
||||
#| msgid "Czech National Bank"
|
||||
msgid "National Bank of Poland"
|
||||
msgstr "Banque nationale tchèque"
|
||||
msgstr "Banque nationale de Pologne"
|
||||
|
||||
#: pretix/base/services/export.py:95 pretix/base/services/export.py:155
|
||||
msgid ""
|
||||
@@ -10396,16 +10392,12 @@ msgstr ""
|
||||
"que le montant de la facture n’est pas en CZK."
|
||||
|
||||
#: pretix/base/settings.py:577 pretix/base/settings.py:586
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Based on Czech National Bank daily rates, whenever the invoice amount is "
|
||||
#| "not in CZK."
|
||||
msgid ""
|
||||
"Based on National Bank of Poland daily rates, whenever the invoice amount is "
|
||||
"not in PLN."
|
||||
msgstr ""
|
||||
"Sur la base des taux journaliers de la Banque nationale tchèque, chaque fois "
|
||||
"que le montant de la facture n’est pas en CZK."
|
||||
"Sur la base des taux quotidiens de la Banque nationale de Pologne, lorsque "
|
||||
"le montant de la facture n'est pas libellé en PLN."
|
||||
|
||||
#: pretix/base/settings.py:597
|
||||
msgid "Require invoice address"
|
||||
@@ -16569,10 +16561,8 @@ msgstr ""
|
||||
"Autoriser à surbooker les quotas lors de l’exécution de cette opération"
|
||||
|
||||
#: pretix/control/forms/orders.py:335
|
||||
#, fuzzy
|
||||
#| msgid "Number of orders"
|
||||
msgid "Number of products to add"
|
||||
msgstr "Nombre de commandes"
|
||||
msgstr "Nombre d'articles à ajouter"
|
||||
|
||||
#: pretix/control/forms/orders.py:344
|
||||
msgid "Add-on to"
|
||||
@@ -16604,10 +16594,10 @@ msgstr ""
|
||||
"produit"
|
||||
|
||||
#: pretix/control/forms/orders.py:441
|
||||
#, fuzzy
|
||||
#| msgid "You can not select the same seat multiple times."
|
||||
msgid "You can not choose a seat when adding multiple products at once."
|
||||
msgstr "Vous ne pouvez pas sélectionner le même siège plusieurs fois."
|
||||
msgstr ""
|
||||
"Vous ne pouvez pas choisir de siège lorsque vous ajoutez plusieurs produits "
|
||||
"à la fois."
|
||||
|
||||
#: pretix/control/forms/orders.py:478 pretix/control/forms/orders.py:482
|
||||
#: pretix/control/forms/orders.py:510 pretix/control/forms/orders.py:552
|
||||
@@ -17230,7 +17220,7 @@ msgstr "Jour de fin de semaine"
|
||||
#: pretix/control/forms/subevents.py:106
|
||||
msgctxt "subevent"
|
||||
msgid "Skip dates that overlap with any existing date"
|
||||
msgstr ""
|
||||
msgstr "Ignorer les dates qui coïncident avec une date existante"
|
||||
|
||||
#: pretix/control/forms/subevents.py:109
|
||||
msgctxt "subevent"
|
||||
@@ -17240,6 +17230,11 @@ msgid ""
|
||||
"This respects even inactive dates and works best if all dates have both a "
|
||||
"start and end time."
|
||||
msgstr ""
|
||||
"Cette option peut s'avérer utile si toutes vos dates se déroulent au même "
|
||||
"endroit et qu'aucune date ne doit être créée en double et entrer en conflit "
|
||||
"avec des événements spéciaux existants. Elle prend en compte même les dates "
|
||||
"inactives et fonctionne mieux si toutes les dates comportent à la fois une "
|
||||
"heure de début et une heure de fin."
|
||||
|
||||
#: pretix/control/forms/subevents.py:128
|
||||
msgid "Keep the current values"
|
||||
@@ -30512,6 +30507,8 @@ msgstr "Veuillez ne pas créer plus de 100.000 dates à la fois."
|
||||
#: pretix/control/views/subevents.py:966
|
||||
msgid "All dates would be skipped because they conflict with existing dates."
|
||||
msgstr ""
|
||||
"Toutes ces dates seraient ignorées car elles entrent en conflit avec des "
|
||||
"dates déjà existantes."
|
||||
|
||||
#: pretix/control/views/subevents.py:1102
|
||||
#, python-brace-format
|
||||
@@ -37887,7 +37884,7 @@ msgstr "Votre panier a été mis à jour."
|
||||
|
||||
#: pretix/presale/views/cart.py:525 pretix/presale/views/cart.py:551
|
||||
msgid "Your cart is now empty."
|
||||
msgstr "Votre panier à été vidé."
|
||||
msgstr "Votre panier a été vidé."
|
||||
|
||||
#: pretix/presale/views/cart.py:584
|
||||
msgid ""
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2024-05-10 15:47+0000\n"
|
||||
"Last-Translator: Martin Gross <gross@rami.io>\n"
|
||||
"PO-Revision-Date: 2026-05-02 23:00+0000\n"
|
||||
"Last-Translator: Daniel Musketa <daniel@musketa.de>\n"
|
||||
"Language-Team: Norwegian Bokmål <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix/nb_NO/>\n"
|
||||
"Language: nb_NO\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.4.3\n"
|
||||
"X-Generator: Weblate 5.17\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -37,11 +37,11 @@ msgstr "Arabisk"
|
||||
|
||||
#: pretix/_base_settings.py:91
|
||||
msgid "Basque"
|
||||
msgstr ""
|
||||
msgstr "Baskisk"
|
||||
|
||||
#: pretix/_base_settings.py:92
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
msgstr "Katalansk"
|
||||
|
||||
#: pretix/_base_settings.py:93
|
||||
msgid "Chinese (simplified)"
|
||||
@@ -57,7 +57,7 @@ msgstr "Tsjekkisk"
|
||||
|
||||
#: pretix/_base_settings.py:96
|
||||
msgid "Croatian"
|
||||
msgstr ""
|
||||
msgstr "Kroatisk"
|
||||
|
||||
#: pretix/_base_settings.py:97
|
||||
msgid "Danish"
|
||||
@@ -89,7 +89,7 @@ msgstr "Gresk"
|
||||
|
||||
#: pretix/_base_settings.py:104
|
||||
msgid "Hebrew"
|
||||
msgstr ""
|
||||
msgstr "Hebraisk"
|
||||
|
||||
#: pretix/_base_settings.py:105
|
||||
msgid "Indonesian"
|
||||
@@ -101,7 +101,7 @@ msgstr "Italiensk"
|
||||
|
||||
#: pretix/_base_settings.py:107
|
||||
msgid "Japanese"
|
||||
msgstr ""
|
||||
msgstr "Japansk"
|
||||
|
||||
#: pretix/_base_settings.py:108
|
||||
msgid "Latvian"
|
||||
@@ -133,11 +133,11 @@ msgstr "Russisk"
|
||||
|
||||
#: pretix/_base_settings.py:115
|
||||
msgid "Slovak"
|
||||
msgstr ""
|
||||
msgstr "Slovakisk"
|
||||
|
||||
#: pretix/_base_settings.py:116
|
||||
msgid "Swedish"
|
||||
msgstr ""
|
||||
msgstr "Svensk"
|
||||
|
||||
#: pretix/_base_settings.py:117
|
||||
msgid "Spanish"
|
||||
@@ -145,7 +145,7 @@ msgstr "Spansk"
|
||||
|
||||
#: pretix/_base_settings.py:118
|
||||
msgid "Spanish (Latin America)"
|
||||
msgstr ""
|
||||
msgstr "Spansk (Latin-Amerika)"
|
||||
|
||||
#: pretix/_base_settings.py:119
|
||||
msgid "Turkish"
|
||||
|
||||
@@ -7,16 +7,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-03-31 17:00+0000\n"
|
||||
"PO-Revision-Date: 2026-05-05 13:26+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\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.16.2\n"
|
||||
"X-Generator: Weblate 5.17.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -8209,10 +8209,8 @@ msgstr ""
|
||||
"2x Add-on 2"
|
||||
|
||||
#: pretix/base/pdf.py:383
|
||||
#, fuzzy
|
||||
#| msgid "List of Add-Ons"
|
||||
msgid "List of Checked-In Add-Ons"
|
||||
msgstr "Lijst met add-ons"
|
||||
msgstr "Lijst met ingecheckte add-ons"
|
||||
|
||||
#: pretix/base/pdf.py:390 pretix/control/forms/filter.py:1537
|
||||
#: pretix/control/forms/filter.py:1539
|
||||
@@ -9206,10 +9204,8 @@ msgid "Czech National Bank"
|
||||
msgstr "Tsjechische Nationale Bank"
|
||||
|
||||
#: pretix/base/services/currencies.py:41
|
||||
#, fuzzy
|
||||
#| msgid "Czech National Bank"
|
||||
msgid "National Bank of Poland"
|
||||
msgstr "Tsjechische Nationale Bank"
|
||||
msgstr "Nationale Bank van Polen"
|
||||
|
||||
#: pretix/base/services/export.py:95 pretix/base/services/export.py:155
|
||||
msgid ""
|
||||
@@ -10296,16 +10292,12 @@ msgstr ""
|
||||
"wanneer het factuurbedrag niet in CZK is."
|
||||
|
||||
#: pretix/base/settings.py:577 pretix/base/settings.py:586
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Based on Czech National Bank daily rates, whenever the invoice amount is "
|
||||
#| "not in CZK."
|
||||
msgid ""
|
||||
"Based on National Bank of Poland daily rates, whenever the invoice amount is "
|
||||
"not in PLN."
|
||||
msgstr ""
|
||||
"Gebaseerd op de dagelijkse tarieven van de Tsjechische Nationale Bank, "
|
||||
"wanneer het factuurbedrag niet in CZK is."
|
||||
"Op basis van de dagkoersen van de Nationale Bank van Polen, wanneer het "
|
||||
"factuurbedrag niet in PLN is uitgedrukt."
|
||||
|
||||
#: pretix/base/settings.py:597
|
||||
msgid "Require invoice address"
|
||||
@@ -16375,10 +16367,8 @@ msgid "Allow to overbook quotas when performing this operation"
|
||||
msgstr "Quota overboeken bij deze handeling toestaan"
|
||||
|
||||
#: pretix/control/forms/orders.py:335
|
||||
#, fuzzy
|
||||
#| msgid "Number of orders"
|
||||
msgid "Number of products to add"
|
||||
msgstr "Aantal bestellingen"
|
||||
msgstr "Aantal producten dat moet worden toegevoegd"
|
||||
|
||||
#: pretix/control/forms/orders.py:344
|
||||
msgid "Add-on to"
|
||||
@@ -16410,10 +16400,9 @@ msgstr ""
|
||||
"standaardprijs van het product"
|
||||
|
||||
#: pretix/control/forms/orders.py:441
|
||||
#, fuzzy
|
||||
#| msgid "You can not select the same seat multiple times."
|
||||
msgid "You can not choose a seat when adding multiple products at once."
|
||||
msgstr "U kunt dezelfde stoel niet meerdere keren kiezen."
|
||||
msgstr ""
|
||||
"U kunt geen zitplaats kiezen wanneer u meerdere producten tegelijk toevoegt."
|
||||
|
||||
#: pretix/control/forms/orders.py:478 pretix/control/forms/orders.py:482
|
||||
#: pretix/control/forms/orders.py:510 pretix/control/forms/orders.py:552
|
||||
@@ -17027,7 +17016,7 @@ msgstr "Weekenddag"
|
||||
#: pretix/control/forms/subevents.py:106
|
||||
msgctxt "subevent"
|
||||
msgid "Skip dates that overlap with any existing date"
|
||||
msgstr ""
|
||||
msgstr "Sla data over die samenvallen met bestaande data"
|
||||
|
||||
#: pretix/control/forms/subevents.py:109
|
||||
msgctxt "subevent"
|
||||
@@ -17037,6 +17026,11 @@ msgid ""
|
||||
"This respects even inactive dates and works best if all dates have both a "
|
||||
"start and end time."
|
||||
msgstr ""
|
||||
"Dit kan handig zijn als alle afspraken op dezelfde locatie plaatsvinden en "
|
||||
"je wilt voorkomen dat terugkerende afspraken in conflict komen met bestaande "
|
||||
"speciale afspraken. Hierbij wordt ook rekening gehouden met inactieve "
|
||||
"afspraken en het werkt het beste als alle afspraken een begin- en eindtijd "
|
||||
"hebben."
|
||||
|
||||
#: pretix/control/forms/subevents.py:128
|
||||
msgid "Keep the current values"
|
||||
@@ -30168,6 +30162,8 @@ msgstr "U kunt maximaal 100.000 datums tegelijk aanmaken."
|
||||
#: pretix/control/views/subevents.py:966
|
||||
msgid "All dates would be skipped because they conflict with existing dates."
|
||||
msgstr ""
|
||||
"Alle afspraken zouden worden overgeslagen omdat ze samenvallen met bestaande "
|
||||
"afspraken."
|
||||
|
||||
#: pretix/control/views/subevents.py:1102
|
||||
#, python-brace-format
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-28 09:03+0000\n"
|
||||
"PO-Revision-Date: 2026-04-08 18:00+0000\n"
|
||||
"PO-Revision-Date: 2026-05-05 13:26+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\n"
|
||||
"Language-Team: Dutch (Belgium) <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix/nl_BE/>\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.16.2\n"
|
||||
"X-Generator: Weblate 5.17.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -8204,10 +8204,8 @@ msgstr ""
|
||||
"2x Add-on 2"
|
||||
|
||||
#: pretix/base/pdf.py:383
|
||||
#, fuzzy
|
||||
#| msgid "List of Add-Ons"
|
||||
msgid "List of Checked-In Add-Ons"
|
||||
msgstr "Lijst met add-ons"
|
||||
msgstr "Lijst met ingecheckte add-ons"
|
||||
|
||||
#: pretix/base/pdf.py:390 pretix/control/forms/filter.py:1537
|
||||
#: pretix/control/forms/filter.py:1539
|
||||
@@ -9202,10 +9200,8 @@ msgid "Czech National Bank"
|
||||
msgstr "Tsjechische Nationale Bank"
|
||||
|
||||
#: pretix/base/services/currencies.py:41
|
||||
#, fuzzy
|
||||
#| msgid "Czech National Bank"
|
||||
msgid "National Bank of Poland"
|
||||
msgstr "Tsjechische Nationale Bank"
|
||||
msgstr "Nationale Bank van Polen"
|
||||
|
||||
#: pretix/base/services/export.py:95 pretix/base/services/export.py:155
|
||||
msgid ""
|
||||
@@ -10293,16 +10289,12 @@ msgstr ""
|
||||
"wanneer het factuurbedrag niet in CZK is."
|
||||
|
||||
#: pretix/base/settings.py:577 pretix/base/settings.py:586
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Based on Czech National Bank daily rates, whenever the invoice amount is "
|
||||
#| "not in CZK."
|
||||
msgid ""
|
||||
"Based on National Bank of Poland daily rates, whenever the invoice amount is "
|
||||
"not in PLN."
|
||||
msgstr ""
|
||||
"Gebaseerd op de dagelijkse tarieven van de Tsjechische Nationale Bank, "
|
||||
"wanneer het factuurbedrag niet in CZK is."
|
||||
"Op basis van de dagkoersen van de Nationale Bank van Polen, wanneer het "
|
||||
"factuurbedrag niet in PLN is uitgedrukt."
|
||||
|
||||
#: pretix/base/settings.py:597
|
||||
msgid "Require invoice address"
|
||||
@@ -16369,10 +16361,8 @@ msgid "Allow to overbook quotas when performing this operation"
|
||||
msgstr "Quota overboeken bij deze handeling toestaan"
|
||||
|
||||
#: pretix/control/forms/orders.py:335
|
||||
#, fuzzy
|
||||
#| msgid "Number of orders"
|
||||
msgid "Number of products to add"
|
||||
msgstr "Aantal bestellingen"
|
||||
msgstr "Aantal producten dat moet worden toegevoegd"
|
||||
|
||||
#: pretix/control/forms/orders.py:344
|
||||
msgid "Add-on to"
|
||||
@@ -16404,10 +16394,9 @@ msgstr ""
|
||||
"standaardprijs van het product"
|
||||
|
||||
#: pretix/control/forms/orders.py:441
|
||||
#, fuzzy
|
||||
#| msgid "You can not select the same seat multiple times."
|
||||
msgid "You can not choose a seat when adding multiple products at once."
|
||||
msgstr "U kunt dezelfde stoel niet meerdere keren kiezen."
|
||||
msgstr ""
|
||||
"U kunt geen zitplaats kiezen wanneer u meerdere producten tegelijk toevoegt."
|
||||
|
||||
#: pretix/control/forms/orders.py:478 pretix/control/forms/orders.py:482
|
||||
#: pretix/control/forms/orders.py:510 pretix/control/forms/orders.py:552
|
||||
@@ -17020,7 +17009,7 @@ msgstr "Weekenddag"
|
||||
#: pretix/control/forms/subevents.py:106
|
||||
msgctxt "subevent"
|
||||
msgid "Skip dates that overlap with any existing date"
|
||||
msgstr ""
|
||||
msgstr "Sla data over die samenvallen met bestaande data"
|
||||
|
||||
#: pretix/control/forms/subevents.py:109
|
||||
msgctxt "subevent"
|
||||
@@ -17030,6 +17019,11 @@ msgid ""
|
||||
"This respects even inactive dates and works best if all dates have both a "
|
||||
"start and end time."
|
||||
msgstr ""
|
||||
"Dit kan handig zijn als alle afspraken op dezelfde locatie plaatsvinden en "
|
||||
"je wilt voorkomen dat terugkerende afspraken in conflict komen met bestaande "
|
||||
"speciale afspraken. Hierbij wordt ook rekening gehouden met inactieve "
|
||||
"afspraken en het werkt het beste als alle afspraken een begin- en eindtijd "
|
||||
"hebben."
|
||||
|
||||
#: pretix/control/forms/subevents.py:128
|
||||
msgid "Keep the current values"
|
||||
@@ -30145,6 +30139,8 @@ msgstr "U kunt maximaal 100.000 datums tegelijk aanmaken."
|
||||
#: pretix/control/views/subevents.py:966
|
||||
msgid "All dates would be skipped because they conflict with existing dates."
|
||||
msgstr ""
|
||||
"Alle afspraken zouden worden overgeslagen omdat ze samenvallen met bestaande "
|
||||
"afspraken."
|
||||
|
||||
#: pretix/control/views/subevents.py:1102
|
||||
#, python-brace-format
|
||||
@@ -31447,10 +31443,16 @@ msgid ""
|
||||
"refunds.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Let op: terugbetalingen zullen als uitgevoerd worden "
|
||||
"gemarkeerd zodra er een exportbestand wordt aangemaakt.\n"
|
||||
" Zorg ervoor dat u het exportbestand downloadt en de "
|
||||
"terugbetalingen daadwerkelijk uitvoert.\n"
|
||||
" "
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:50
|
||||
msgid "Exported files"
|
||||
msgstr ""
|
||||
msgstr "Geëxporteerde bestanden"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:55
|
||||
msgid "Export date"
|
||||
@@ -31462,17 +31464,17 @@ msgstr "Aantal bestellingen"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:80
|
||||
msgid "not downloaded"
|
||||
msgstr ""
|
||||
msgstr "niet gedownload"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:85
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:96
|
||||
msgid "Download CSV"
|
||||
msgstr ""
|
||||
msgstr "CSV downloaden"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:90
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:101
|
||||
msgid "SEPA XML"
|
||||
msgstr ""
|
||||
msgstr "SEPA-XML"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/refund_export.html:110
|
||||
msgid "No exports have been created yet."
|
||||
@@ -31480,7 +31482,7 @@ msgstr "Er zijn nog geen exports aangemaakt."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/sepa_export.html:10
|
||||
msgid "Export SEPA xml"
|
||||
msgstr ""
|
||||
msgstr "Exporteer SEPA-XML"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/sepa_export.html:13
|
||||
#, python-format
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from django.db import migrations
|
||||
from django.db.models import F
|
||||
|
||||
|
||||
def remove_cross_event_scheduled_mails(apps, schema_editor):
|
||||
Rule = apps.get_model("sendmail", "Rule")
|
||||
ScheduledMail = apps.get_model("sendmail", "ScheduledMail")
|
||||
ScheduledMail.objects.filter(rule__subevent__isnull=False).exclude(rule__subevent__event=F('rule__event')).delete()
|
||||
Rule.objects.filter(subevent__isnull=False).exclude(subevent__event=F('event')).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("sendmail", "0010_auto_20250801_1342"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(remove_cross_event_scheduled_mails),
|
||||
]
|
||||
@@ -232,7 +232,7 @@ def sendmail_copy_data_receiver(sender, other, item_map, **kwargs):
|
||||
if sender.sendmail_rules.exists(): # idempotency
|
||||
return
|
||||
|
||||
for r in other.sendmail_rules.prefetch_related('limit_products'):
|
||||
for r in other.sendmail_rules.filter(subevent__isnull=True).prefetch_related('limit_products'):
|
||||
limit_products = list(r.limit_products.all())
|
||||
r = copy.copy(r)
|
||||
r.pk = None
|
||||
|
||||
@@ -386,7 +386,7 @@ class StripeSettingsHolder(BasePaymentProvider):
|
||||
disabled=self.event.currency != 'EUR',
|
||||
help_text=(
|
||||
_('Some payment methods might need to be enabled in the settings of your Stripe account '
|
||||
'before work properly.') +
|
||||
'before they work properly.') +
|
||||
'<div class="alert alert-warning">%s</div>' % _(
|
||||
'SEPA Direct Debit payments via Stripe are <strong>not</strong> processed '
|
||||
'instantly but might take up to <strong>14 days</strong> to be confirmed in some cases. '
|
||||
|
||||
@@ -34,6 +34,7 @@ from compressor.filters.jsmin import rJSMinFilter
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.core.files.base import ContentFile, File
|
||||
from django.core.files.storage import default_storage
|
||||
from django.db.models import Q
|
||||
@@ -676,7 +677,10 @@ class WidgetAPIProductList(EventListMixin, View):
|
||||
for d in data['days']:
|
||||
d['events'] = self._serialize_events(d['events'] or [])
|
||||
else:
|
||||
offset = int(self.request.GET.get("offset", 0))
|
||||
try:
|
||||
offset = int(self.request.GET.get("offset", 0))
|
||||
except ValueError:
|
||||
raise BadRequest('GET parameter "offset" must be an integer.')
|
||||
limit = 50
|
||||
if hasattr(self.request, 'event'):
|
||||
evs = filter_qs_by_attr(
|
||||
|
||||
@@ -265,7 +265,7 @@ EMAIL_USE_TLS = config.getboolean('mail', 'tls', fallback=False)
|
||||
EMAIL_USE_SSL = config.getboolean('mail', 'ssl', fallback=False)
|
||||
EMAIL_SUBJECT_PREFIX = '[pretix] '
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_CUSTOM_SMTP_BACKEND = 'pretixbase.email.CheckPrivateNetworkSmtpBackend'
|
||||
EMAIL_CUSTOM_SMTP_BACKEND = 'pretix.base.email.CheckPrivateNetworkSmtpBackend'
|
||||
EMAIL_TIMEOUT = 60
|
||||
|
||||
ADMINS = [('Admin', n) for n in config.get('mail', 'admins', fallback='').split(",") if n]
|
||||
|
||||
56
src/pretix/static/npm_dir/package-lock.json
generated
56
src/pretix/static/npm_dir/package-lock.json
generated
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.28.5",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@rollup/plugin-babel": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"rollup": "^2.79.1",
|
||||
@@ -32,9 +32,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
|
||||
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
|
||||
"integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@@ -439,6 +439,21 @@
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz",
|
||||
"integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
|
||||
@@ -1301,17 +1316,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz",
|
||||
"integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.3.tgz",
|
||||
"integrity": "sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.29.0",
|
||||
"@babel/compat-data": "^7.29.3",
|
||||
"@babel/helper-compilation-targets": "^7.28.6",
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-validator-option": "^7.27.1",
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
|
||||
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
|
||||
"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6",
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||
@@ -3751,9 +3767,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/compat-data": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
|
||||
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
|
||||
"integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg=="
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.28.5",
|
||||
@@ -4033,6 +4049,15 @@
|
||||
"@babel/helper-plugin-utils": "^7.27.1"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz",
|
||||
"integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
|
||||
@@ -4532,17 +4557,18 @@
|
||||
}
|
||||
},
|
||||
"@babel/preset-env": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz",
|
||||
"integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.3.tgz",
|
||||
"integrity": "sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==",
|
||||
"requires": {
|
||||
"@babel/compat-data": "^7.29.0",
|
||||
"@babel/compat-data": "^7.29.3",
|
||||
"@babel/helper-compilation-targets": "^7.28.6",
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-validator-option": "^7.27.1",
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
|
||||
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
|
||||
"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6",
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.28.5",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@rollup/plugin-babel": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"vue": "^2.7.16",
|
||||
|
||||
@@ -25,10 +25,11 @@ from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
from django.core import mail as djmail
|
||||
from django.db.models import F
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.models import InvoiceAddress, Order
|
||||
from pretix.base.models import Event, InvoiceAddress, Order
|
||||
from pretix.base.services.checkin import perform_checkin
|
||||
from pretix.plugins.sendmail.models import Rule, ScheduledMail
|
||||
from pretix.plugins.sendmail.signals import sendmail_run_rules
|
||||
@@ -687,3 +688,41 @@ def test_sendmail_context_localization(event, order, pos):
|
||||
|
||||
sendmail_run_rules(None)
|
||||
assert "Hallo Herr Mustermann" in djmail.outbox[0].body
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_event_clone_ignores_rules_with_subevent(event, order, pos):
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
se1 = event.subevents.create(name="subevent 1", date_from=dt_now)
|
||||
|
||||
event.sendmail_rules.create(date_is_absolute=False, send_offset_days=1, send_offset_time=datetime.time(hour=12),
|
||||
subject='Mail To Subevent', template='TestBody', subevent=se1)
|
||||
event.sendmail_rules.create(date_is_absolute=False, send_offset_days=1, send_offset_time=datetime.time(hour=12),
|
||||
subject='Mail To All', template='TestBody')
|
||||
|
||||
assert event.sendmail_rules.count() == 2
|
||||
assert event.scheduledmail_set.count() == 2
|
||||
for rule in event.sendmail_rules.all():
|
||||
assert rule.scheduledmail_set.count() == 1
|
||||
|
||||
copied_event = Event.objects.create(
|
||||
organizer=event.organizer, name='Dummy2', slug='dummy2',
|
||||
date_from=datetime.datetime(2022, 4, 15, 9, 0, 0, tzinfo=datetime.timezone.utc),
|
||||
has_subevents=True
|
||||
)
|
||||
copied_event.copy_data_from(event)
|
||||
copied_event.refresh_from_db()
|
||||
event.refresh_from_db()
|
||||
|
||||
assert copied_event.sendmail_rules.count() == 1
|
||||
assert copied_event.sendmail_rules.first().scheduledmail_set.count() == 0
|
||||
assert str(copied_event.sendmail_rules.first().subject) == "Mail To All"
|
||||
|
||||
copied_event.subevents.create(name="subevent 1 in copied", date_from=dt_now)
|
||||
assert copied_event.sendmail_rules.first().scheduledmail_set.count() == 1
|
||||
|
||||
# Double-Check: no scheduled mails and rules exist where subevent.event and event do not align
|
||||
assert ScheduledMail.objects.filter(rule__subevent__isnull=False).exclude(rule__subevent__event=F('rule__event')).count() == 0
|
||||
assert Rule.objects.filter(subevent__isnull=False).exclude(subevent__event=F('event')).count() == 0
|
||||
|
||||
Reference in New Issue
Block a user