Compare commits

..
Author SHA1 Message Date
Raphael Michel 7841cf1ce6 Add sort option 2024-10-31 13:01:19 +01:00
959e775c40 Update src/pretix/plugins/badges/exporters.py
Co-authored-by: Mira <weller@rami.io>
2024-10-31 13:00:34 +01:00
80403f2700 Update src/pretix/plugins/badges/exporters.py
Co-authored-by: Mira <weller@rami.io>
2024-10-31 13:00:29 +01:00
Raphael Michel 308e97f143 Badge export: Allow to filter by order date (Z#23168742) 2024-10-29 16:18:16 +01:00
46 changed files with 3324 additions and 3019 deletions
+23 -6
View File
@@ -31,6 +31,8 @@ subevent integer ID of the date
position_count integer Number of tickets that match this list (read-only).
checkin_count integer Number of check-ins performed on this list (read-only).
include_pending boolean If ``true``, the check-in list also contains tickets from orders in pending state.
auto_checkin_sales_channels list of strings All items on the check-in list will be automatically marked as checked-in when purchased through any of the listed sales channels.
**Deprecated, will be removed in pretix 2024.10.** Use :ref:`rest-autocheckinrules`: instead.
allow_multiple_entries boolean If ``true``, subsequent scans of a ticket on this list should not show a warning but instead be stored as an additional check-in.
allow_entry_after_exit boolean If ``true``, subsequent scans of a ticket on this list are valid if the last scan of the ticket was an exit scan.
rules object Custom check-in logic. The contents of this field are currently not considered a stable API and modifications through the API are highly discouraged.
@@ -89,7 +91,10 @@ Endpoints
"allow_entry_after_exit": true,
"exit_all_at": null,
"rules": {},
"addon_match": false
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
}
]
}
@@ -141,7 +146,10 @@ Endpoints
"allow_entry_after_exit": true,
"exit_all_at": null,
"rules": {},
"addon_match": false
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -238,7 +246,10 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
}
**Example response**:
@@ -260,7 +271,10 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
}
:param organizer: The ``slug`` field of the organizer of the event/item to create a list for
@@ -312,7 +326,10 @@ Endpoints
"subevent": null,
"allow_multiple_entries": false,
"allow_entry_after_exit": true,
"addon_match": false
"addon_match": false,
"auto_checkin_sales_channels": [
"pretixpos"
]
}
:param organizer: The ``slug`` field of the organizer to modify
@@ -325,7 +342,7 @@ Endpoints
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/checkinlist/(id)/
Delete a check-in list. **Note that this also deletes the information on all check-ins performed via this list.**
Delete a check-in list. Note that this also deletes the information on all check-ins performed via this list.
**Example request**:
+3 -12
View File
@@ -104,10 +104,6 @@ url string The full URL to
payments list of objects List of payment processes (see below)
refunds list of objects List of refund processes (see below)
last_modified datetime Last modification of this object
cancellation_date datetime Time of order cancellation (or ``null``). **Note**:
Will not be set for partial cancellations and is not
reliable for orders that have been cancelled,
reactivated and cancelled again.
===================================== ========================== =======================================================
@@ -155,9 +151,6 @@ cancellation_date datetime Time of order c
The ``expires`` attribute can now be passed during order creation.
.. versionchanged:: 2024.11
The ``cancellation_date`` attribute has been added and can also be used as an ordering key.
.. _order-position-resource:
@@ -471,15 +464,14 @@ List of all orders
"provider": "banktransfer"
}
],
"refunds": [],
"cancellation_date": null
"refunds": []
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``code``,
``last_modified``, ``status`` and ``cancellation_date``. Default: ``datetime``
``last_modified``, and ``status``. Default: ``datetime``
:query string code: Only return orders that match the given order code
:query string status: Only return orders in the given order status (see above)
:query string search: Only return orders matching a given search query (matching for names, email addresses, and company names)
@@ -711,8 +703,7 @@ Fetching individual orders
"provider": "banktransfer"
}
],
"refunds": [],
"cancellation_date": null
"refunds": []
}
:param organizer: The ``slug`` field of the organizer to fetch
+3 -2
View File
@@ -91,8 +91,9 @@ dependencies = [
"redis==5.2.*",
"reportlab==4.2.*",
"requests==2.31.*",
"sentry-sdk==2.18.*",
"sentry-sdk==2.17.*",
"sepaxml==2.6.*",
"slimit",
"stripe==7.9.*",
"text-unidecode==1.*",
"tlds>=2020041600",
@@ -116,7 +117,7 @@ dev = [
"isort==5.13.*",
"pep8-naming==0.14.*",
"potypo",
"pytest-asyncio>=0.24",
"pytest-asyncio",
"pytest-cache",
"pytest-cov",
"pytest-django==4.*",
+11 -2
View File
@@ -26,22 +26,31 @@ from rest_framework.exceptions import ValidationError
from pretix.api.serializers.event import SubEventSerializer
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.base.media import MEDIA_TYPES
from pretix.base.models import Checkin, CheckinList
from pretix.base.models import Checkin, CheckinList, SalesChannel
class CheckinListSerializer(I18nAwareModelSerializer):
checkin_count = serializers.IntegerField(read_only=True)
position_count = serializers.IntegerField(read_only=True)
auto_checkin_sales_channels = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
many=True,
)
class Meta:
model = CheckinList
fields = ('id', 'name', 'all_products', 'limit_products', 'subevent', 'checkin_count', 'position_count',
'include_pending', 'allow_multiple_entries', 'allow_entry_after_exit',
'include_pending', 'auto_checkin_sales_channels', 'allow_multiple_entries', 'allow_entry_after_exit',
'rules', 'exit_all_at', 'addon_match', 'ignore_in_statistics', 'consider_tickets_used')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['auto_checkin_sales_channels'].child_relation.queryset = self.context['event'].organizer.sales_channels.all()
if 'subevent' in self.context['request'].query_params.getlist('expand'):
self.fields['subevent'] = SubEventSerializer(read_only=True)
+2 -2
View File
@@ -753,12 +753,12 @@ class OrderSerializer(I18nAwareModelSerializer):
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
'url', 'customer', 'valid_if_pending', 'api_meta', 'cancellation_date'
'url', 'customer', 'valid_if_pending', 'api_meta'
)
read_only_fields = (
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'positions', 'downloads', 'customer',
'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel', 'cancellation_date'
'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel'
)
def __init__(self, *args, **kwargs):
+1 -3
View File
@@ -116,7 +116,7 @@ class CheckinListViewSet(viewsets.ModelViewSet):
if 'subevent' in self.request.query_params.getlist('expand'):
qs = qs.prefetch_related(
'subevent', 'subevent__event', 'subevent__subeventitem_set', 'subevent__subeventitemvariation_set',
'subevent__seat_category_mappings', 'subevent__meta_values',
'subevent__seat_category_mappings', 'subevent__meta_values', 'auto_checkin_sales_channels'
)
return qs
@@ -143,9 +143,7 @@ class CheckinListViewSet(viewsets.ModelViewSet):
data=self.request.data
)
@transaction.atomic
def perform_destroy(self, instance):
instance.checkins.all().delete()
instance.log_action(
'pretix.event.checkinlist.deleted',
user=self.request.user,
+1 -1
View File
@@ -215,7 +215,7 @@ class OrderViewSetMixin:
queryset = Order.objects.none()
filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
ordering = ('datetime',)
ordering_fields = ('datetime', 'code', 'status', 'last_modified', 'cancellation_date')
ordering_fields = ('datetime', 'code', 'status', 'last_modified')
filterset_class = OrderFilter
lookup_field = 'code'
@@ -1,48 +0,0 @@
# Generated by Django 4.2.16 on 2024-10-29 15:03
from django.db import migrations
def migrate_autocheckin(apps, schema_editor):
CheckinList = apps.get_model("pretixbase", "CheckinList")
AutoCheckinRule = apps.get_model("autocheckin", "AutoCheckinRule")
for cl in CheckinList.objects.filter(auto_checkin_sales_channels__isnull=False).select_related("event", "event__organizer"):
sales_channels = cl.auto_checkin_sales_channels.all()
all_sales_channels = cl.event.organizer.sales_channels.all()
if "pretix.plugins.autocheckin" not in cl.event.plugins:
cl.event.plugins = cl.event.plugins + ",pretix.plugins.autocheckin"
cl.event.save()
r = AutoCheckinRule.objects.get_or_create(
list=cl,
event=cl.event,
all_products=True,
all_payment_methods=True,
defaults=dict(
mode="placed",
all_sales_channels=len(sales_channels) == len(all_sales_channels),
)
)[0]
if len(sales_channels) != len(all_sales_channels):
r.limit_sales_channels.set(sales_channels)
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0272_printlog"),
("autocheckin", "0001_initial"),
]
operations = [
migrations.RunPython(
migrate_autocheckin,
migrations.RunPython.noop,
),
migrations.RemoveField(
model_name="checkinlist",
name="auto_checkin_sales_channels",
),
]
+11 -7
View File
@@ -99,6 +99,14 @@ class CheckinList(LoggedModel):
verbose_name=_('Automatically check out everyone at'),
null=True, blank=True
)
auto_checkin_sales_channels = models.ManyToManyField(
"SalesChannel",
verbose_name=_('Sales channels to automatically check in'),
help_text=_('This option is deprecated and will be removed in the next months. As a replacement, our new plugin '
'"Auto check-in" can be used. When we remove this option, we will automatically migrate your event '
'to use the new plugin.'),
blank=True,
)
rules = models.JSONField(default=dict, blank=True)
objects = ScopedManager(organizer='event__organizer')
@@ -133,7 +141,7 @@ class CheckinList(LoggedModel):
return self.positions_query(ignore_status=False)
@scopes_disabled()
def _filter_positions_inside(self, qs, at_time=None):
def positions_inside_query(self, ignore_status=False, at_time=None):
if at_time is None:
c_q = []
else:
@@ -141,7 +149,7 @@ class CheckinList(LoggedModel):
if "postgresql" not in settings.DATABASES["default"]["ENGINE"]:
# Use a simple approach that works on all databases
qs = qs.annotate(
qs = self.positions_query(ignore_status=ignore_status).annotate(
last_entry=Subquery(
Checkin.objects.filter(
*c_q,
@@ -194,7 +202,7 @@ class CheckinList(LoggedModel):
.values("position_id", "type", "datetime", "cnt_exists_after")
.query.sql_with_params()
)
return qs.filter(
return self.positions_query(ignore_status=ignore_status).filter(
pk__in=RawSQL(
f"""
SELECT "position_id"
@@ -206,10 +214,6 @@ class CheckinList(LoggedModel):
)
)
@scopes_disabled()
def positions_inside_query(self, ignore_status=False, at_time=None):
return self._filter_positions_inside(self.positions_query(ignore_status=ignore_status), at_time=at_time)
@property
def positions_inside(self):
return self.positions_inside_query(None)
+4 -1
View File
@@ -1024,9 +1024,10 @@ class Event(EventMixin, LoggedModel):
checkin_list_map = {}
for cl in other.checkin_lists.filter(subevent__isnull=True).prefetch_related(
'limit_products'
'limit_products', 'auto_checkin_sales_channels'
):
items = list(cl.limit_products.all())
auto_checkin_sales_channels = list(cl.auto_checkin_sales_channels.all())
checkin_list_map[cl.pk] = cl
cl.pk = None
cl._prefetched_objects_cache = {}
@@ -1038,6 +1039,8 @@ class Event(EventMixin, LoggedModel):
cl.log_action('pretix.object.cloned')
for i in items:
cl.limit_products.add(item_map[i.pk])
if auto_checkin_sales_channels:
cl.auto_checkin_sales_channels.set(self.organizer.sales_channels.filter(identifier__in=[s.identifier for s in auto_checkin_sales_channels]))
if other.seating_plan:
if other.seating_plan.organizer_id == self.organizer_id:
-3
View File
@@ -343,13 +343,11 @@ class CartManager:
err = error_messages['some_subevent_not_started']
cp.addons.all().delete()
cp.delete()
continue
if cp.subevent and cp.subevent.presale_end and time_machine_now(self.real_now_dt) > cp.subevent.presale_end:
err = error_messages['some_subevent_ended']
cp.addons.all().delete()
cp.delete()
continue
if cp.subevent:
tlv = self.event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
@@ -362,7 +360,6 @@ class CartManager:
err = error_messages['some_subevent_ended']
cp.addons.all().delete()
cp.delete()
continue
return err
def _update_subevents_cache(self, se_ids: List[int]):
+18 -1
View File
@@ -57,7 +57,7 @@ from pretix.base.models import (
Checkin, CheckinList, Device, Event, Gate, Item, ItemVariation, Order,
OrderPosition, QuestionOption,
)
from pretix.base.signals import checkin_created, periodic_task
from pretix.base.signals import checkin_created, order_placed, periodic_task
from pretix.helpers import OF_SELF
from pretix.helpers.jsonlogic import Logic
from pretix.helpers.jsonlogic_boolalg import convert_to_dnf
@@ -1154,6 +1154,23 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
)
@receiver(order_placed, dispatch_uid="legacy_autocheckin_order_placed")
def order_placed(sender, **kwargs):
order = kwargs['order']
event = sender
cls = list(event.checkin_lists.filter(auto_checkin_sales_channels=order.sales_channel).prefetch_related(
'limit_products'))
if not cls:
return
for op in order.positions.all():
for cl in cls:
if cl.all_products or op.item_id in {i.pk for i in cl.limit_products.all()}:
if not cl.subevent_id or cl.subevent_id == op.subevent_id:
ci = Checkin.objects.create(position=op, list=cl, auto_checked_in=True, type=Checkin.TYPE_ENTRY)
checkin_created.send(event, checkin=ci)
@receiver(periodic_task, dispatch_uid="autocheckout_exit_all")
@scopes_disabled()
def process_exit_all(sender, **kwargs):
+9 -1
View File
@@ -33,7 +33,9 @@ from django_scopes.forms import (
from pretix.base.forms.widgets import SplitDateTimePickerWidget
from pretix.base.models import Gate
from pretix.base.models.checkin import Checkin, CheckinList
from pretix.control.forms import ItemMultipleChoiceField
from pretix.control.forms import (
ItemMultipleChoiceField, SalesChannelCheckboxSelectMultiple,
)
from pretix.control.forms.widgets import Select2
@@ -65,6 +67,10 @@ class CheckinListForm(forms.ModelForm):
kwargs.pop('locales', None)
super().__init__(**kwargs)
self.fields['limit_products'].queryset = self.event.items.all()
self.fields['auto_checkin_sales_channels'].queryset = self.event.organizer.sales_channels.all()
self.fields['auto_checkin_sales_channels'].widget = SalesChannelCheckboxSelectMultiple(
self.event, choices=self.fields['auto_checkin_sales_channels'].widget.choices
)
if not self.event.organizer.gates.exists():
del self.fields['gates']
@@ -96,6 +102,7 @@ class CheckinListForm(forms.ModelForm):
'limit_products',
'subevent',
'include_pending',
'auto_checkin_sales_channels',
'allow_multiple_entries',
'allow_entry_after_exit',
'rules',
@@ -118,6 +125,7 @@ class CheckinListForm(forms.ModelForm):
'limit_products': ItemMultipleChoiceField,
'gates': SafeModelMultipleChoiceField,
'subevent': SafeModelChoiceField,
'auto_checkin_sales_channels': SafeModelMultipleChoiceField,
'exit_all_at': NextTimeField,
}
+1 -1
View File
@@ -1967,7 +1967,7 @@ class CheckinListAttendeeFilterForm(FilterForm):
if s == '1':
qs = qs.filter(last_entry__isnull=False)
elif s == '2':
qs = self.list._filter_positions_inside(qs)
qs = qs.filter(pk__in=self.list.positions_inside.values_list('pk'))
elif s == '3':
qs = qs.filter(last_entry__isnull=False).filter(
Q(last_exit__isnull=False) & Q(last_exit__gte=F('last_entry'))
-43
View File
@@ -609,49 +609,6 @@ class OrderFeeChangeForm(forms.Form):
change_decimal_field(self.fields['value'], instance.order.event.currency)
class OrderFeeAddForm(forms.Form):
fee_type = forms.ChoiceField(choices=OrderFee.FEE_TYPES)
value = forms.DecimalField(
max_digits=13, decimal_places=2,
localize=True,
label=_('Price'),
help_text=_("including all taxes"),
)
tax_rule = forms.ModelChoiceField(
TaxRule.objects.none(),
required=False,
)
description = forms.CharField(required=False)
def __init__(self, *args, **kwargs):
order = kwargs.pop('order')
super().__init__(*args, **kwargs)
self.fields['tax_rule'].queryset = order.event.tax_rules.all()
change_decimal_field(self.fields['value'], order.event.currency)
class OrderFeeAddFormset(forms.BaseFormSet):
def __init__(self, *args, **kwargs):
self.order = kwargs.pop('order', None)
super().__init__(*args, **kwargs)
def _construct_form(self, i, **kwargs):
kwargs['order'] = self.order
return super()._construct_form(i, **kwargs)
@property
def empty_form(self):
form = self.form(
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
order=self.order,
)
self.add_fields(form, None)
return form
class OrderContactForm(forms.ModelForm):
regenerate_secrets = forms.BooleanField(required=False, label=_('Invalidate secrets'),
help_text=_('Regenerates the order and ticket secrets. You will '
@@ -67,6 +67,7 @@
{% bootstrap_field form.allow_entry_after_exit layout="control" %}
{% bootstrap_field form.addon_match layout="control" %}
{% bootstrap_field form.exit_all_at layout="control" %}
{% bootstrap_field form.auto_checkin_sales_channels layout="control" %}
{% if form.gates %}
{% bootstrap_field form.gates layout="control" %}
{% endif %}
@@ -101,6 +101,7 @@
<a href="?{% url_replace request 'ordering' 'subevent' %}"><i class="fa fa-caret-up"></i></a>
</th>
{% endif %}
<th class="iconcol">{% trans "Automated check-in" %}</th>
<th>{% trans "Products" %}</th>
<th class="action-col-2"></th>
</tr>
@@ -136,6 +137,17 @@
</td>
{% endif %}
{% endif %}
<td>
{% for channel in cl.auto_checkin_sales_channels.all %}
{% if "." in channel.icon %}
<img src="{% static channel.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ channel.label }}">
{% else %}
<span class="fa fa-{{ channel.icon }} text-muted"
data-toggle="tooltip" title="{{ channel.label }}"></span>
{% endif %}
{% endfor %}
</td>
<td>
{% if cl.all_products %}
<em>{% trans "All" %}</em>
@@ -16,18 +16,8 @@
{% bootstrap_field form.internal_name layout="control" %}
</div>
{% bootstrap_field form.description layout="control" %}
{% bootstrap_field form.category_type layout="control" horizontal_field_class="big-radio-wrapper col-md-9" %}
<div class="row" data-display-dependency="#id_category_type_2">
<div class="col-md-offset-3 col-md-9">
<div class="alert alert-info">
{% blocktrans trimmed %}
Please note that cross-selling categories are intended as a marketing feature and are not
suitable for strictly ensuring that products are only available in certain combinations.
{% endblocktrans %}
</div>
</div>
</div>
{% bootstrap_field form.cross_selling_condition layout="control" horizontal_field_class="col-md-9" %}
{% bootstrap_field form.category_type layout="control" horizontal_field_class="big-radio-wrapper col-lg-9" %}
{% bootstrap_field form.cross_selling_condition layout="control" horizontal_field_class="col-lg-9" %}
{% bootstrap_field form.cross_selling_match_products layout="control" %}
</fieldset>
</div>
@@ -296,11 +296,11 @@
{% endfor %}
<div class="formset" data-formset data-formset-prefix="{{ add_position_formset.prefix }}">
{{ add_position_formset.management_form }}
{% bootstrap_formset_errors add_position_formset %}
<div class="formset" data-formset data-formset-prefix="{{ add_formset.prefix }}">
{{ add_formset.management_form }}
{% bootstrap_formset_errors add_formset %}
<div data-formset-body>
{% for add_form in add_position_formset %}
{% for add_form in add_formset %}
<div class="panel panel-default items" data-formset-form data-subevent="0">
<div class="panel-heading">
<h3 class="panel-title">
@@ -351,25 +351,25 @@
</button>
{% trans "Add product" %}
<div class="sr-only">
{{ add_position_formset.empty_form.id }}
{% bootstrap_field add_position_formset.empty_form.DELETE form_group_class="" layout="inline" %}
{{ add_formset.empty_form.id }}
{% bootstrap_field add_formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
</h3>
</div>
<div class="panel-body">
<div class="form-horizontal">
{% bootstrap_field add_position_formset.empty_form.itemvar layout="control" %}
{% bootstrap_field add_position_formset.empty_form.price addon_after=request.event.currency layout="control" %}
{% if add_position_formset.empty_form.addon_to %}
{% bootstrap_field add_position_formset.empty_form.addon_to layout="control" %}
{% bootstrap_field add_formset.empty_form.itemvar layout="control" %}
{% bootstrap_field add_formset.empty_form.price addon_after=request.event.currency layout="control" %}
{% if add_formset.empty_form.addon_to %}
{% bootstrap_field add_formset.empty_form.addon_to layout="control" %}
{% endif %}
{% if add_position_formset.empty_form.subevent %}
{% bootstrap_field add_position_formset.empty_form.subevent layout="control" %}
{% if add_formset.empty_form.subevent %}
{% bootstrap_field add_formset.empty_form.subevent layout="control" %}
{% endif %}
{% if add_position_formset.empty_form.used_membership %}
{% bootstrap_field add_position_formset.empty_form.used_membership layout="control" %}
{% if add_formset.empty_form.used_membership %}
{% bootstrap_field add_formset.empty_form.used_membership layout="control" %}
{% endif %}
{% bootstrap_field add_position_formset.empty_form.seat layout="control" %}
{% bootstrap_field add_formset.empty_form.seat layout="control" %}
</div>
</div>
</div>
@@ -431,77 +431,13 @@
{% bootstrap_field fee.form.operation_cancel layout='inline' %}
{% if fee.fee_type == "payment" %}
<em class="text-danger">
{% trans "Manually modifying payment fees is discouraged since they might automatically be updated on subsequent order changes or when choosing a different payment method." %}
{% trans "Manually modifying payment fees is discouraged since they might automatically be on subsequent order changes or when choosing a different payment method." %}
</em>
{% endif %}
</div>
</div>
</div>
{% endfor %}
<div class="formset" data-formset data-formset-prefix="{{ add_fee_formset.prefix }}">
{{ add_fee_formset.management_form }}
{% bootstrap_formset_errors add_fee_formset %}
<div data-formset-body>
{% for add_form in add_fee_formset %}
<div class="panel panel-default items" data-formset-form data-subevent="0">
<div class="panel-heading">
<h3 class="panel-title">
<button type="button" class="btn btn-danger btn-xs pull-right flip"
data-formset-delete-button>
<i class="fa fa-trash"></i>
</button>
{% trans "Add fee" %}
<div class="sr-only">
{{ add_form.id }}
{% bootstrap_field add_form.DELETE form_group_class="" layout="inline" %}
</div>
</h3>
</div>
<div class="panel-body">
<div class="form-horizontal">
{% bootstrap_field add_form.fee_type layout='control' %}
{% bootstrap_field add_form.value addon_after=request.event.currency layout='control' %}
{% bootstrap_field add_form.tax_rule layout='control' %}
{% bootstrap_field add_form.description layout='control' %}
</div>
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div class="panel panel-default items" data-formset-form data-subevent="0">
<div class="panel-heading">
<h3 class="panel-title">
<button type="button" class="btn btn-danger btn-xs pull-right flip"
data-formset-delete-button>
<i class="fa fa-trash"></i>
</button>
{% trans "Add fee" %}
<div class="sr-only">
{{ add_fee_formset.empty_form.id }}
{% bootstrap_field add_fee_formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
</h3>
</div>
<div class="panel-body">
<div class="form-horizontal">
{% bootstrap_field add_fee_formset.empty_form.fee_type layout='control' %}
{% bootstrap_field add_fee_formset.empty_form.value addon_after=request.event.currency layout='control' %}
{% bootstrap_field add_fee_formset.empty_form.tax_rule layout='control' %}
{% bootstrap_field add_fee_formset.empty_form.description layout='control' %}
</div>
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-primary" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add fee" %}</button>
</p>
</div>
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
@@ -198,7 +198,7 @@
</a>
{% endif %}
</dd>
{% if order.status == "n" and not order.require_approval %}
{% if order.status == "n" %}
<dt>{% trans "Expiry date" %}</dt>
<dd>
{{ order.expires|date:"SHORT_DATETIME_FORMAT" }}
+1 -1
View File
@@ -299,7 +299,7 @@ class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
def get_queryset(self):
qs = self.request.event.checkin_lists.select_related('subevent').prefetch_related(
"limit_products",
"limit_products", "auto_checkin_sales_channels"
)
if self.filter_form.is_valid():
+1 -1
View File
@@ -257,7 +257,7 @@ class CategoryUpdate(EventPermissionRequiredMixin, UpdateView):
messages.success(self.request, _('Your changes have been saved.'))
if form.has_changed():
self.object.log_action(
'pretix.event.category.changed', user=self.request.user, data={
'pretix.event.category.reordered', user=self.request.user, data={
k: form.cleaned_data.get(k) for k in form.changed_data
}
)
+14 -55
View File
@@ -122,11 +122,10 @@ from pretix.control.forms.filter import (
)
from pretix.control.forms.orders import (
CancelForm, CommentForm, DenyForm, EventCancelForm, ExporterForm,
ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeAddForm,
OrderFeeAddFormset, OrderFeeChangeForm, OrderLocaleForm, OrderMailForm,
OrderPositionAddForm, OrderPositionAddFormset, OrderPositionChangeForm,
OrderPositionMailForm, OrderRefundForm, OtherOperationsForm,
ReactivateOrderForm,
ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeChangeForm,
OrderLocaleForm, OrderMailForm, OrderPositionAddForm,
OrderPositionAddFormset, OrderPositionChangeForm, OrderPositionMailForm,
OrderRefundForm, OtherOperationsForm, ReactivateOrderForm,
)
from pretix.control.forms.rrule import RRuleForm
from pretix.control.permissions import EventPermissionRequiredMixin
@@ -1875,30 +1874,18 @@ class OrderChange(OrderView):
data=self.request.POST if self.request.method == "POST" else None)
@cached_property
def add_position_formset(self):
def add_formset(self):
ff = formset_factory(
OrderPositionAddForm, formset=OrderPositionAddFormset,
can_order=False, can_delete=True, extra=0
)
return ff(
prefix='add_position',
prefix='add',
order=self.order,
items=self.items,
data=self.request.POST if self.request.method == "POST" else None
)
@cached_property
def add_fee_formset(self):
ff = formset_factory(
OrderFeeAddForm, formset=OrderFeeAddFormset,
can_order=False, can_delete=True, extra=0
)
return ff(
prefix='add_fee',
order=self.order,
data=self.request.POST if self.request.method == "POST" else None
)
@cached_property
def items(self):
return self.request.event.items.prefetch_related('variations', 'tax_rule').all()
@@ -1927,8 +1914,7 @@ class OrderChange(OrderView):
ctx = super().get_context_data(**kwargs)
ctx['positions'] = self.positions
ctx['fees'] = self.fees
ctx['add_position_formset'] = self.add_position_formset
ctx['add_fee_formset'] = self.add_fee_formset
ctx['add_formset'] = self.add_formset
ctx['other_form'] = self.other_form
ctx['use_revocation_list'] = self.request.event.ticket_secret_generator.use_revocation_list
return ctx
@@ -1943,35 +1929,12 @@ class OrderChange(OrderView):
)
return True
def _process_add_fees(self, ocm):
if not self.add_fee_formset.is_valid():
def _process_add(self, ocm):
if not self.add_formset.is_valid():
return False
else:
for f in self.add_fee_formset.forms:
if f in self.add_fee_formset.deleted_forms or not f.has_changed():
continue
f = OrderFee(
fee_type=f.cleaned_data['fee_type'],
value=f.cleaned_data['value'],
order=ocm.order,
tax_rule=f.cleaned_data['tax_rule'],
description=f.cleaned_data['description'],
)
f._calculate_tax()
try:
ocm.add_fee(f)
except OrderError as e:
f.custom_error = str(e)
return False
return True
def _process_add_positions(self, ocm):
if not self.add_position_formset.is_valid():
return False
else:
for f in self.add_position_formset.forms:
if f in self.add_position_formset.deleted_forms or not f.has_changed():
for f in self.add_formset.forms:
if f in self.add_formset.deleted_forms or not f.has_changed():
continue
if '-' in f.cleaned_data['itemvar']:
@@ -1996,7 +1959,7 @@ class OrderChange(OrderView):
return False
return True
def _process_change_fees(self, ocm):
def _process_fees(self, ocm):
for f in self.fees:
if not f.form.is_valid():
return False
@@ -2017,7 +1980,7 @@ class OrderChange(OrderView):
return False
return True
def _process_change_positions(self, ocm):
def _process_change(self, ocm):
for p in self.positions:
if not p.form.is_valid():
return False
@@ -2098,11 +2061,7 @@ class OrderChange(OrderView):
notify=notify,
reissue_invoice=self.other_form.cleaned_data['reissue_invoice'] if self.other_form.is_valid() else True
)
form_valid = (self._process_add_fees(ocm) and
self._process_add_positions(ocm) and
self._process_change_fees(ocm) and
self._process_change_positions(ocm) and
self._process_other(ocm))
form_valid = self._process_add(ocm) and self._process_fees(ocm) and self._process_change(ocm) and self._process_other(ocm)
if not form_valid:
messages.error(self.request, _('An error occurred. Please see the details below.'))
+7 -7
View File
@@ -4,8 +4,8 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-29 08:53+0000\n"
"PO-Revision-Date: 2024-11-04 13:44+0000\n"
"Last-Translator: Katrine Tella <ktl@hjoerring.dk>\n"
"PO-Revision-Date: 2024-07-19 03:00+0000\n"
"Last-Translator: Nikolai <nikolai@lengefeldt.de>\n"
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/da/"
">\n"
"Language: da\n"
@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.8.1\n"
"X-Generator: Weblate 5.6.2\n"
#: pretix/_base_settings.py:79
msgid "English"
@@ -16642,9 +16642,8 @@ msgstr "Login"
#: pretix/control/templates/pretixcontrol/auth/invite.html:27
#: pretix/control/templates/pretixcontrol/auth/login.html:43
#: pretix/control/templates/pretixcontrol/auth/register.html:22
#, fuzzy
msgid "Register"
msgstr "Tilmeld"
msgstr "Registrer"
#: pretix/control/templates/pretixcontrol/auth/login.html:27
#: pretix/presale/templates/pretixpresale/fragment_login_status.html:19
@@ -30950,7 +30949,7 @@ msgstr "Kontroller venligst detaljerne nedenfor og bekræft din bestilling."
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:14
msgid "Please hang tight, we're finalizing your order!"
msgstr "Hæng venligst på, mens vi genererer din bestilling!"
msgstr "Hæng venligst på, mens vi generer din bestilling!"
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:22
msgid "Add or remove tickets"
@@ -32119,9 +32118,10 @@ msgstr "Aktivér venteliste"
#: pretix/presale/templates/pretixpresale/event/index.html:217
#: pretix/presale/templates/pretixpresale/event/voucher.html:437
#, fuzzy
msgctxt "free_tickets"
msgid "Register"
msgstr "Tilmeld"
msgstr "Registrer"
#: pretix/presale/templates/pretixpresale/event/index.html:222
#: pretix/presale/templates/pretixpresale/event/voucher.html:442
File diff suppressed because it is too large Load Diff
+10 -8
View File
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-15 11:06+0000\n"
"PO-Revision-Date: 2024-11-01 19:00+0000\n"
"PO-Revision-Date: 2024-10-22 17:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/"
"pretix-js/es/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.8.1\n"
"X-Generator: Weblate 5.7.2\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -326,13 +326,13 @@ msgstr "Tickets válidos"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
msgid "Currently inside"
msgstr "Actualmente en el interior"
msgstr "Actualmente adentro"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
#: pretix/static/pretixcontrol/js/ui/question.js:137
#: pretix/static/pretixpresale/js/ui/questions.js:270
msgid "Yes"
msgstr "Si"
msgstr "Sí"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:72
#: pretix/static/pretixcontrol/js/ui/question.js:138
@@ -570,8 +570,10 @@ msgid "Group of objects"
msgstr "Grupo de objetos"
#: pretix/static/pretixcontrol/js/ui/editor.js:899
#, fuzzy
#| msgid "Text object"
msgid "Text object (deprecated)"
msgstr "Objeto texto (obsoleto)"
msgstr "Objeto de texto"
#: pretix/static/pretixcontrol/js/ui/editor.js:901
msgid "Text box"
@@ -702,12 +704,12 @@ msgid ""
"The items in your cart are no longer reserved for you. You can still "
"complete your order as long as theyre available."
msgstr ""
"Los elementos en su cesta de compras ya no se encuentran reservados. Puedes "
"seguir añadiendo más productos mientras estén disponibles."
"Los elementos en su carrito de compras ya no se encuentran reservados. "
"Puedes seguir añadiendo más productos mientras estén disponibles."
#: pretix/static/pretixpresale/js/ui/cart.js:45
msgid "Cart expired"
msgstr "La cesta de compra ha expirado"
msgstr "El carrito de compras ha expirado"
#: pretix/static/pretixpresale/js/ui/cart.js:50
msgid "The items in your cart are reserved for you for one minute."
+137 -78
View File
@@ -4,7 +4,7 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-29 08:53+0000\n"
"PO-Revision-Date: 2024-11-05 20:00+0000\n"
"PO-Revision-Date: 2024-10-21 11:25+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
">\n"
@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.8.1\n"
"X-Generator: Weblate 5.7.2\n"
#: pretix/_base_settings.py:79
msgid "English"
@@ -271,7 +271,9 @@ msgstr "La propriété de métadonnées '{name}' n'existe pas."
#: pretix/api/serializers/item.py:207 pretix/control/forms/item.py:1269
msgid "The bundled item must not be the same item as the bundling one."
msgstr "Un produit groupé ne peut pas se contenir lui-même."
msgstr ""
"Un produit qui est un groupement de produits ne doit pas comprendre le "
"produit groupé."
#: pretix/api/serializers/item.py:210 pretix/control/forms/item.py:1271
msgid "The bundled item must not have bundles on its own."
@@ -654,15 +656,16 @@ msgstr ""
"Votre mot de passe doit contenir des caractères numériques et alphabétiques."
#: pretix/base/auth.py:202 pretix/base/auth.py:212
#, python-format
#, fuzzy, python-format
msgid "Your password may not be the same as your previous password."
msgid_plural ""
"Your password may not be the same as one of your %(history_length)s previous "
"passwords."
msgstr[0] "Votre mot de passe doit être différent de votre mot de passe précédent."
msgstr[0] ""
"Votre mot de passe doit être différent de votre mot de passe précédent."
msgstr[1] ""
"Votre mot de passe doit être différent de vos %(history_length)s derniers "
"mot de passe."
"Votre mot de passe doit être différent de vos %(history_length) derniers mot "
"de passe."
#: pretix/base/channels.py:168
msgid "Online shop"
@@ -1925,7 +1928,7 @@ msgstr ""
#: pretix/base/exporters/waitinglist.py:113 pretix/control/forms/event.py:1585
#: pretix/control/forms/organizer.py:115
msgid "Event slug"
msgstr "Étiquette de l'événement"
msgstr "Nom court de l'évènement"
#: pretix/base/exporters/orderlist.py:261 pretix/base/notifications.py:201
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:25
@@ -2831,6 +2834,10 @@ msgid "Reusable media"
msgstr "Support réutilisable"
#: pretix/base/exporters/reusablemedia.py:36
#, fuzzy
#| msgid ""
#| "Download a spreadsheet with information on all events in this organizer "
#| "account."
msgid ""
"Download a spread sheet with the data of all reusable medias on your account."
msgstr ""
@@ -3061,7 +3068,7 @@ msgstr "Rue et numéro"
#: pretix/base/forms/questions.py:717 pretix/base/forms/questions.py:1059
msgctxt "address"
msgid "Select state"
msgstr "Choisir un état"
msgstr "Sélectionner l'état"
#: pretix/base/forms/questions.py:1046
msgid ""
@@ -3171,7 +3178,8 @@ msgid ""
msgstr ""
#: pretix/base/forms/validators.py:72 pretix/control/views/event.py:763
#, python-format
#, fuzzy, python-format
#| msgid "Invalid placeholder(s): %(value)s"
msgid "Invalid placeholder: {%(value)s}"
msgstr "Caractère générique invalide : %(value)s"
@@ -3404,8 +3412,8 @@ msgid ""
"Using the conversion rate of 1:{rate} as published by the {authority} on "
"{date}, this corresponds to:"
msgstr ""
"En utilisant le taux de conversion de 1 :{rate} publié par {authority} le "
"{date}, cela correspond à :"
"En utilisant le taux de conversion de 1:{rate} publié par {authority} le "
"{date}, cela correspond à :"
#: pretix/base/invoice.py:844
#, python-brace-format
@@ -3460,9 +3468,10 @@ msgid "Invalid setting for column \"{header}\"."
msgstr "Paramètre non valide pour la colonne \"{header}\"."
#: pretix/base/modelimport.py:199
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid "Could not parse {value} as a date and time."
msgid "Could not parse {value} as a yes/no value."
msgstr "Impossible danalyser {value} comme une réponse oui/non."
msgstr "Impossible danalyser {value} comme date et heure."
#: pretix/base/modelimport.py:222
#, python-brace-format
@@ -3657,7 +3666,7 @@ msgstr "Utilisation maximale"
#: pretix/base/modelimport_vouchers.py:79
msgid "The maximum number of usages must be set."
msgstr "Le nombre maximum d'utilisations doit être spécifié."
msgstr "Le nombre maximum d'utilisations doit être fixé."
#: pretix/base/modelimport_vouchers.py:88 pretix/base/models/vouchers.py:205
msgid "Minimum usages"
@@ -3752,10 +3761,12 @@ msgstr ""
"ce bon"
#: pretix/base/models/auth.py:248
#, fuzzy
msgid "Is active"
msgstr "Actif"
#: pretix/base/models/auth.py:250
#, fuzzy
msgid "Is site admin"
msgstr "Administrateur du site"
@@ -3937,7 +3948,7 @@ msgstr "Interdit par une règle personnalisée"
#: pretix/base/models/checkin.py:362
msgid "Ticket code revoked/changed"
msgstr "Code ticket révoqué/modifié"
msgstr "Code du billet révoqué/modifié"
#: pretix/base/models/checkin.py:363
msgid "Information required"
@@ -4071,6 +4082,7 @@ msgstr "Cet identificateur est déjà utilisé pour une autre question."
#: pretix/control/templates/pretixcontrol/checkin/checkins.html:67
#: pretix/control/templates/pretixcontrol/organizers/gates.html:16
#: pretix/plugins/checkinlists/exporters.py:763
#, fuzzy
msgid "Gate"
msgstr "Pont"
@@ -4105,8 +4117,10 @@ msgid "Position"
msgstr "Position"
#: pretix/base/models/discount.py:70
#, fuzzy
#| msgid "Sales channels"
msgid "All supported sales channels"
msgstr "Tous les canaux de vente pris en charge"
msgstr "Canaux de vente"
#: pretix/base/models/discount.py:91
msgid "Event series handling"
@@ -4325,8 +4339,10 @@ msgid "Seating plan"
msgstr "Plan de salle"
#: pretix/base/models/event.py:642 pretix/base/models/items.py:666
#, fuzzy
#| msgid "Sales channels"
msgid "Sell on all sales channels"
msgstr "Vendre sur tous les canaux de vente"
msgstr "Canaux de vente"
#: pretix/base/models/event.py:647 pretix/base/models/items.py:671
#: pretix/base/models/items.py:1217 pretix/base/payment.py:417
@@ -6166,10 +6182,10 @@ msgid "Team members"
msgstr "Membres de l'équipe"
#: pretix/base/models/organizer.py:289
#, fuzzy
#| msgid "Do you really want to disable two-factor authentication?"
msgid "Require all members of this team to use two-factor authentication"
msgstr ""
"Exiger que tous les membres de cette équipe utilisent l'authentification à "
"deux facteurs"
msgstr "Voulez-vous vraiment désactiver l'authentification à deux facteurs ?"
#: pretix/base/models/organizer.py:290
msgid ""
@@ -7681,14 +7697,16 @@ msgstr ""
"dans la quantité sélectionnée. Voir ci-dessous pour plus de détails."
#: pretix/base/services/cart.py:117
#, python-format
#, fuzzy, python-format
#| msgid ""
#| "Some of the products you selected are no longer available in the quantity "
#| "you selected. Please see below for details."
msgid ""
"Some of the products you selected are no longer available. The following "
"products are affected and have not been added to your cart: %s"
msgstr ""
"Certains des produits que vous avez sélectionnés ne sont plus disponibles "
"dans la quantité sélectionnée. Les produits suivants sont concernés et n'ont "
"pas été ajoutés à votre panier : %s"
"dans la quantité sélectionnée. Voir ci-dessous pour plus de détails."
#: pretix/base/services/cart.py:121
#, python-format
@@ -8425,17 +8443,20 @@ msgstr ""
"fois, ce qui est le montant maximum."
#: pretix/base/services/memberships.py:227
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid ""
#| "You are trying to use a membership of type \"{type}\" for an event taking "
#| "place at {date}, however you already used the same membership for a "
#| "different ticket at the same time."
msgid ""
"You are trying to use a membership of type \"{type}\" for a ticket valid "
"from {valid_from} until {valid_until}, however you already used the same "
"membership for a different ticket that overlaps with this time frame "
"({conflict_from} {conflict_until})."
msgstr ""
"Vous essayez d'utiliser une adhésion de type « {type} » pour un ticket "
"valable de {valid_from} à {valid_until}, mais vous avez déjà utilisé la même "
"adhésion pour un autre ticket qui chevauche cette période ({conflict_from} - "
"{conflict_until})."
"Vous essayez d'utiliser une adhésion de type \"{type}\" pour un événement se "
"déroulant à {date}, Cependant, vous avez déjà utilisé la même adhésion pour "
"un ticket différent en même temps."
#: pretix/base/services/memberships.py:231
#: pretix/base/services/memberships.py:233
@@ -10228,17 +10249,22 @@ msgid "No modifications after order was submitted"
msgstr ""
#: pretix/base/settings.py:1682 pretix/base/settings.py:1691
#, fuzzy
#| msgid "Only pending or paid orders can be changed."
msgid "Only the person who ordered can make changes"
msgstr ""
"Seule la personne qui a passé la commande peut apporter des modifications"
msgstr "Seules les commandes en attente ou payées peuvent être modifiées."
#: pretix/base/settings.py:1683 pretix/base/settings.py:1692
msgid "Both the attendee and the person who ordered can make changes"
msgstr ""
#: pretix/base/settings.py:1687
#, fuzzy
#| msgid "Allow customers to modify their information after they checked in."
msgid "Allow customers to modify their information"
msgstr "Permettre aux clients de modifier leurs informations"
msgstr ""
"Permettre aux clients de modifier leurs informations après leur "
"enregistrement."
#: pretix/base/settings.py:1702
msgid "Allow customers to modify their information after they checked in."
@@ -11320,13 +11346,13 @@ msgid ""
msgstr ""
"Bonjour\n"
"\n"
"Nous avons approuvé votre commande pour l'événement {event}, et serons "
"heureux de vous accueillir\n"
"Votre commande ne comprend que des produits gratuits, aucun paiement nest "
"requis.\n"
"Nous avons approuvé votre commande pour l'événement {event}\n"
"et serons heureux de vous accueillir\n"
"Votre commande ne comprend que des produits gratuits, \n"
"aucun paiement nest requis.\n"
"\n"
"Vous pouvez modifier les détails de votre commande et consulter son état à l"
"adresse suivante :\n"
"Vous pouvez modifier les détails de votre commande et consulter son état à "
"ladresse suivante :\n"
"{url}\n"
"\n"
"Sincères salutations\n"
@@ -11977,7 +12003,7 @@ msgstr "M."
#: pretix/base/settings.py:3428
msgctxt "person_name_salutation"
msgid "Mx"
msgstr "Non binaire ou ne souhaite pas répondre"
msgstr "Mx"
#: pretix/base/settings.py:3460 pretix/base/settings.py:3473
#: pretix/base/settings.py:3489 pretix/base/settings.py:3539
@@ -12111,9 +12137,10 @@ msgstr ""
"La dernière date de paiement ne peut être antérieure à la fin de la prévente."
#: pretix/base/settings.py:3824
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid "Please enter a valid sales channel."
msgid "The value \"{identifier}\" is not a valid sales channel."
msgstr "La valeur \"{identifier}\" n'est pas un canal de vente valide."
msgstr "Veuillez saisir un canal de vente valide."
#: pretix/base/settings.py:3839
msgid "This needs to be disabled if other NFC-based types are active."
@@ -14377,11 +14404,11 @@ msgstr ""
"Assurez-vous de le tenir à jour!"
#: pretix/control/forms/item.py:100
#, fuzzy
#| msgid "Products in this category are add-on products"
msgid ""
"Products in this category are regular products displayed on the front page."
msgstr ""
"Les produits de cette catégorie sont des produits standard et sont affichés "
"sur la page d'accueil."
msgstr "Les produits de cette catégorie sont des Add-Ons"
#: pretix/control/forms/item.py:103
#, fuzzy
@@ -14390,12 +14417,12 @@ msgid "Add-on product category"
msgstr "Catégorie de produit"
#: pretix/control/forms/item.py:104
#, fuzzy
#| msgid "Products in this category are add-on products"
msgid ""
"Products in this category are add-on products and can only be bought as add-"
"ons."
msgstr ""
"Les produits de cette catégorie sont des produits complémentaires et ne "
"peuvent être achetés qu'en tant que tels."
msgstr "Les produits de cette catégorie sont des Add-Ons"
#: pretix/control/forms/item.py:108
msgid ""
@@ -14515,10 +14542,10 @@ msgstr ""
"toutes les parties de l'événement, sauf l'espace VIP."
#: pretix/control/forms/item.py:664
#, fuzzy
#| msgid "The ordered product \"{item}\" is no longer available."
msgid "Show product with info on why its unavailable"
msgstr ""
"Afficher le produit avec des informations sur la raison de son "
"indisponibilité"
msgstr "Le produit commandé \"{item}\" n'est plus disponible."
#: pretix/control/forms/item.py:677
msgid ""
@@ -16869,9 +16896,11 @@ msgstr ""
"annulé."
#: pretix/control/logdisplay.py:644
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid ""
#| "Position #{posid} has been scanned at {datetime} for list \"{list}\"."
msgid "Position #{posid} has been printed at {datetime} with type \"{type}\"."
msgstr "Position #{posid} a été scannée à {datetime} pour la liste \"{type}\"."
msgstr "Position #{posid} a été scannée à {datetime} pour la liste \"{list}\"."
#: pretix/control/logdisplay.py:667
#, python-brace-format
@@ -17751,7 +17780,10 @@ msgid "Delete check-ins"
msgstr "Supprimer la liste d'enregistrement"
#: pretix/control/templates/pretixcontrol/checkin/bulk_revert_confirm.html:15
#, python-format
#, fuzzy, python-format
#| msgid ""
#| "Are you sure you want to delete the check-in list <strong>%(name)s</"
#| "strong>?"
msgid ""
"Are you sure you want to permanently delete the check-ins of <strong>one "
"ticket</strong>."
@@ -17759,11 +17791,11 @@ msgid_plural ""
"Are you sure you want to permanently delete the check-ins of "
"<strong>%(count)s tickets</strong>?"
msgstr[0] ""
"Êtes-vous sûr de vouloir supprimer l'enregistrement <strong>d'un billet</"
"strong>?"
"Êtes-vous sûr de vouloir supprimer la liste d'enregistrement "
"<strong>%(name)s</strong>?"
msgstr[1] ""
"Êtes-vous sûr de vouloir supprimer l'enregistrement <strong>%(count)s "
"billets</strong>?"
"Êtes-vous sûr de vouloir supprimer la liste d'enregistrement "
"<strong>%(name)s</strong>?"
#: pretix/control/templates/pretixcontrol/checkin/bulk_revert_confirm.html:24
#: pretix/control/templates/pretixcontrol/checkin/list_delete.html:18
@@ -21026,8 +21058,11 @@ msgstr ""
"Actuellement indisponible car une durée limitée pour ce produit a été fixée"
#: pretix/control/templates/pretixcontrol/items/discounts.html:111
#, fuzzy
#| msgctxt "discount"
#| msgid "Condition"
msgid "Condition:"
msgstr "Condition :"
msgstr "Condition"
#: pretix/control/templates/pretixcontrol/items/discounts.html:126
msgid "Applies to:"
@@ -22997,7 +23032,7 @@ msgstr "Allez à la billetterie"
#: pretix/control/templates/pretixcontrol/orders/index.html:35
msgid "Search query:"
msgstr "Requête de recherche :"
msgstr "Recherche :"
#: pretix/control/templates/pretixcontrol/orders/index.html:50
#: pretix/control/templates/pretixcontrol/vouchers/index.html:20
@@ -23202,8 +23237,10 @@ msgid "Channel type"
msgstr "Type de scan"
#: pretix/control/templates/pretixcontrol/organizers/channel_delete.html:5
#, fuzzy
#| msgid "Sales channel"
msgid "Delete sales channel:"
msgstr "Supprimez les canaux de vente :"
msgstr "Canal de vente"
#: pretix/control/templates/pretixcontrol/organizers/channel_delete.html:10
#, fuzzy
@@ -23224,8 +23261,10 @@ msgstr ""
"commande. Remplacez sa date de fin par le passé."
#: pretix/control/templates/pretixcontrol/organizers/channel_edit.html:6
#, fuzzy
#| msgid "Sales channel"
msgid "Sales channel:"
msgstr "Canaux de vente :"
msgstr "Canal de vente"
#: pretix/control/templates/pretixcontrol/organizers/channels.html:8
msgid ""
@@ -25070,8 +25109,10 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/subevents/fragment_unavail_mode_indicator.html:3
#: pretix/control/templates/pretixcontrol/subevents/fragment_unavail_mode_indicator.html:5
#, fuzzy
#| msgid "Can change product settings"
msgid "You can change this option in the product settings."
msgstr "Vous pouvez modifier cette option dans les paramètres du produit."
msgstr "Possibilité de modifier les paramètres du produit"
#: pretix/control/templates/pretixcontrol/subevents/index.html:11
msgid "You haven't created any dates for this event series yet."
@@ -25333,10 +25374,10 @@ msgstr "Désactiver l'authentification à deux facteurs !"
#: pretix/control/templates/pretixcontrol/user/2fa_main.html:29
#: pretix/control/templates/pretixcontrol/user/2fa_main.html:75
#, fuzzy
#| msgid "Obligatory usage of two-factor authentication"
msgid "As an administrator, you need to use two-factor authentication."
msgstr ""
"Utilisation obligatoire de lauthentification à deux facteurs pour les "
"administrateurs."
msgstr "Utilisation obligatoire de lauthentification à deux facteurs"
#: pretix/control/templates/pretixcontrol/user/2fa_main.html:33
#: pretix/control/templates/pretixcontrol/user/2fa_main.html:77
@@ -27778,10 +27819,10 @@ msgstr ""
"correctement."
#: pretix/control/views/user.py:583
#, fuzzy
#| msgid "Do you really want to enable two-factor authentication?"
msgid "You have left all teams that require two-factor authentication."
msgstr ""
"Vous avez supprimé toutes les équipes qui doivent s'authentifier par deux "
"facteurs."
msgstr "Voulez-vous vraiment activer l'authentification à deux facteurs ?"
#: pretix/control/views/user.py:597
msgid ""
@@ -27963,8 +28004,10 @@ msgid "Login from new source detected"
msgstr "Aucun code de commande détecté"
#: pretix/helpers/security.py:170
#, fuzzy
#| msgid "Unknown country code."
msgid "Unknown country"
msgstr "Pays inconnu"
msgstr "Code de pays inconnu."
#: pretix/multidomain/models.py:36
msgid "Known domain"
@@ -28783,13 +28826,16 @@ msgstr ""
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_confirm.html:36
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:36
#, fuzzy
#| msgid ""
#| "After completing your purchase, we will ask you to transfer the money to "
#| "the following bank account, using a personal reference code:"
msgid ""
"After completing your purchase, we will ask you to transfer the money to our "
"bank account, using a personal reference code."
msgstr ""
"Après avoir effectué votre achat, nous vous demanderons de virer l'argent "
"sur le compte bancaire suivant, en mentionnant la référence suivante dans "
"l'objet du virement."
"sur le compte bancaire suivant, en utilisant un code de référence personnel:"
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_confirm.html:43
#, python-format
@@ -31777,12 +31823,16 @@ msgid "Enter the entity number, reference number, and amount."
msgstr ""
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:25
#, fuzzy
#| msgid "Invoice number"
msgid "Entity number:"
msgstr "Numéro de l'entité :"
msgstr "Numéro de facture"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:26
#, fuzzy
#| msgid "Reference code"
msgid "Reference number:"
msgstr "Numéro de référence :"
msgstr "Code de référence"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:35
msgid ""
@@ -32927,9 +32977,10 @@ msgstr "Nouveau prix :"
#: pretix/presale/templates/pretixpresale/event/voucher.html:176
#: pretix/presale/templates/pretixpresale/event/voucher.html:328
#: pretix/presale/templates/pretixpresale/event/voucher.html:330
#, python-format
#, fuzzy, python-format
#| msgid "Modify price for %(item)s"
msgid "Modify price for %(item)s, at least %(price)s"
msgstr "Modifier le prix pour %(item)s, prix minimum %(price)s"
msgstr "Modifier le prix pour %(item)s"
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:152
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:291
@@ -33041,12 +33092,16 @@ msgid "Enter a voucher code below to buy this product."
msgstr "Entrez un code de réduction ci-dessous pour acheter ce billet."
#: pretix/presale/templates/pretixpresale/event/fragment_availability.html:10
#, fuzzy
#| msgid "Not available"
msgid "Not available yet."
msgstr "Pas encore disponible."
msgstr "Non disponible"
#: pretix/presale/templates/pretixpresale/event/fragment_availability.html:14
#, fuzzy
#| msgid "Not available"
msgid "Not available any more."
msgstr "Plus disponible."
msgstr "Non disponible"
#: pretix/presale/templates/pretixpresale/event/fragment_availability.html:19
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:85
@@ -33977,6 +34032,8 @@ msgid "Change your order"
msgstr "Changer l'ordre"
#: pretix/presale/templates/pretixpresale/event/order.html:353
#, fuzzy
#| msgid "Cancel order"
msgctxt "action"
msgid "Cancel your order"
msgstr "Annuler la commande"
@@ -34989,8 +35046,10 @@ msgid "This feature is only available in test mode."
msgstr "Cette carte cadeau ne peut être utilisée quen mode test."
#: pretix/presale/views/event.py:985
#, fuzzy
#| msgid "This account is disabled."
msgid "Time machine disabled!"
msgstr "Le mode \"machine à remonter le temps \" est désactivé !"
msgstr "Ce compte est désactivé."
#: pretix/presale/views/order.py:368 pretix/presale/views/order.py:433
#: pretix/presale/views/order.py:514
+5 -4
View File
@@ -7,8 +7,8 @@ msgstr ""
"Project-Id-Version: French\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-15 11:06+0000\n"
"PO-Revision-Date: 2024-11-01 02:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"PO-Revision-Date: 2024-06-12 03:00+0000\n"
"Last-Translator: simonD <simon.dalvy@gmail.com>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
"fr/>\n"
"Language: fr\n"
@@ -16,7 +16,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.8.1\n"
"X-Generator: Weblate 5.5.5\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -293,7 +293,7 @@ msgstr "Entrée non autorisée"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
msgid "Ticket code revoked/changed"
msgstr "Code ticket révoqué/modifié"
msgstr "Code du billet révoqué/modifié"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
msgid "Ticket blocked"
@@ -452,6 +452,7 @@ msgid "Product variation"
msgstr "Variation du produit"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
#, fuzzy
msgid "Gate"
msgstr "Pont"
+55 -48
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-29 08:53+0000\n"
"PO-Revision-Date: 2024-11-07 08:26+0000\n"
"Last-Translator: Damiano <estux@users.noreply.translate.pretix.eu>\n"
"PO-Revision-Date: 2024-10-26 00:00+0000\n"
"Last-Translator: Davide Manzella <manzella.davide97@gmail.com>\n"
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix/"
"it/>\n"
"Language: it\n"
@@ -3708,10 +3708,10 @@ msgstr ""
"sola."
#: pretix/base/modelimport_vouchers.py:306 pretix/base/models/vouchers.py:519
#, python-brace-format
#, fuzzy, python-brace-format
msgid "You need to choose the product \"{prod}\" for this seat."
msgstr ""
"E' necessario scegliere il prodotto \"{prod}\" per questo posto a sedere."
"è necessario sceglliere il prodotto \"[prod}\" per questo posto a sedere."
#: pretix/base/modelimport_vouchers.py:318 pretix/base/models/vouchers.py:285
#: pretix/control/templates/pretixcontrol/vouchers/index.html:129
@@ -4342,7 +4342,7 @@ msgid ""
"You have configured at least one paid product but have not enabled any "
"payment methods."
msgstr ""
"È stato configurato almeno un prodotto a pagamento ma non è stato abilitato "
"È stato configurato almento un prodotto a pagamento ma non è stato abilitato "
"alcun metodo di pagamento."
#: pretix/base/models/event.py:1295
@@ -4375,7 +4375,7 @@ msgstr "Lo slug di questo evento non può essere modificato."
#: pretix/base/models/event.py:1419
msgid "This slug has already been used for a different event."
msgstr "Questo slug è già stato utilizzato per un altro evento."
msgstr "Questo slug è stato già utlizzato per un altro evento."
#: pretix/base/models/event.py:1425
msgid "The event cannot end before it starts."
@@ -4398,20 +4398,18 @@ msgid ""
"If selected, this event will show up publicly on the list of dates for your "
"event."
msgstr ""
"Se questa opzione è selezionata, questo evento apparirà pubblicamente "
"nell'elenco delle date del vostro evento."
#: pretix/base/models/event.py:1510 pretix/base/settings.py:3019
msgid "Frontpage text"
msgstr "Testo della pagina principale"
msgstr ""
#: pretix/base/models/event.py:1527
msgid "Date in event series"
msgstr "Data nella serie di eventi"
msgstr ""
#: pretix/base/models/event.py:1528
msgid "Dates in event series"
msgstr "Date della serie di eventi"
msgstr ""
#: pretix/base/models/event.py:1673
msgid "One or more variations do not belong to this event."
@@ -4419,27 +4417,26 @@ msgstr "Una o più varianti non appartengono a questo evento."
#: pretix/base/models/event.py:1703 pretix/base/models/items.py:2194
msgid "Can not contain spaces or special characters except underscores"
msgstr "Non può contenere spazi o caratteri speciali, tranne i trattini bassi"
msgstr ""
#: pretix/base/models/event.py:1708 pretix/base/models/items.py:2199
msgid "The property name may only contain letters, numbers and underscores."
msgstr ""
"Il nome della proprietà può contenere solamente lettere, numeri e trattini "
"bassi."
#: pretix/base/models/event.py:1713
#, fuzzy
msgid "Default value"
msgstr "Valore predefinito"
msgstr "Valore netto"
#: pretix/base/models/event.py:1715
#: pretix/control/templates/pretixcontrol/organizers/properties.html:50
msgid "Can only be changed by organizer-level administrators"
msgstr ""
"Può essere modificato solo dagli amministratori a livello di organizzatore"
#: pretix/base/models/event.py:1717
#, fuzzy
msgid "Required for events"
msgstr "Necessario per gli eventi"
msgstr "Rimborso o pagamento esterno"
#: pretix/base/models/event.py:1718
msgid ""
@@ -4448,26 +4445,28 @@ msgid ""
msgstr ""
#: pretix/base/models/event.py:1724 pretix/base/models/items.py:2211
#, fuzzy
msgid "Valid values"
msgstr "Valori validi"
msgstr "Tasse"
#: pretix/base/models/event.py:1727
#: pretix/control/templates/pretixcontrol/organizers/properties.html:45
msgid "Show filter option to customers"
msgstr "Mostra l'opzione filtro ai clienti"
msgstr ""
#: pretix/base/models/event.py:1728
msgid ""
"This field will be shown to filter events in the public event list and "
"calendar."
msgstr ""
"Questo campo verrà visualizzato per filtrare gli eventi nell'elenco di "
"eventi pubblici e nel calendario."
#: pretix/base/models/event.py:1731 pretix/control/forms/organizer.py:223
#: pretix/control/forms/organizer.py:227
#, fuzzy
#| msgctxt "openidconnect"
#| msgid "Public"
msgid "Public name"
msgstr "Nome pubblico"
msgstr "Pubblico"
#: pretix/base/models/event.py:1735
#: pretix/control/templates/pretixcontrol/organizers/properties.html:40
@@ -4592,16 +4591,14 @@ msgstr "Nome della categoria"
msgid ""
"If you set this, this will be used instead of the public name in the backend."
msgstr ""
"Se imposti questa opzione, verrà utilizzata nel backend al posto del nome "
"pubblico."
#: pretix/base/models/items.py:101
msgid "Category description"
msgstr "Descrizione della categoria"
msgstr ""
#: pretix/base/models/items.py:108
msgid "Products in this category are add-on products"
msgstr "I prodotti in questa categoria sono prodotti aggiuntivi"
msgstr ""
#: pretix/base/models/items.py:109
msgid ""
@@ -4612,8 +4609,10 @@ msgstr ""
#: pretix/base/models/items.py:114 pretix/base/models/items.py:159
#: pretix/control/forms/item.py:99
#, fuzzy
#| msgid "Product category"
msgid "Normal category"
msgstr "Categoria normale"
msgstr "Categoria prodotto"
#: pretix/base/models/items.py:115 pretix/control/forms/item.py:112
msgid "Normal + cross-selling category"
@@ -4634,7 +4633,7 @@ msgstr ""
#: pretix/base/models/items.py:126
msgid "Only show if the cart contains one of the following products"
msgstr "Mostra solo se il carrello contiene uno dei seguenti prodotti"
msgstr ""
#: pretix/base/models/items.py:129
msgid "Cross-selling condition"
@@ -4654,9 +4653,9 @@ msgid "Product categories"
msgstr "Categorie prodotto"
#: pretix/base/models/items.py:149
#, fuzzy, python-brace-format
#, python-brace-format
msgid "{category} ({category_type})"
msgstr "{category} ({category_type})"
msgstr ""
#: pretix/base/models/items.py:155
#, fuzzy
@@ -4666,21 +4665,22 @@ msgstr "Categoria prodotto"
#: pretix/base/models/items.py:222 pretix/base/models/items.py:278
msgid "Disable product for this date"
msgstr "Disattiva il prodotto per questa data"
msgstr ""
#: pretix/base/models/items.py:226 pretix/base/models/items.py:282
#: pretix/base/models/items.py:560
msgid "This product will not be sold before the given date."
msgstr "Questo prodotto non sarà venduto prima della data indicata."
msgstr ""
#: pretix/base/models/items.py:231 pretix/base/models/items.py:287
#: pretix/base/models/items.py:570
msgid "This product will not be sold after the given date."
msgstr "Questo prodotto non sarà venduto dopo la data indicata."
msgstr ""
#: pretix/base/models/items.py:436
#, fuzzy
msgid "Event validity (default)"
msgstr "Validità dell'evento (predefinita)"
msgstr "(Default per l'evento)"
#: pretix/base/models/items.py:437
#, fuzzy
@@ -4689,12 +4689,14 @@ msgstr "Cliente"
#: pretix/base/models/items.py:438
msgid "Dynamic validity"
msgstr "Validità dinamica"
msgstr ""
#: pretix/base/models/items.py:444 pretix/control/forms/item.py:663
#: pretix/control/templates/pretixcontrol/subevents/fragment_unavail_mode_indicator.html:3
#, fuzzy
#| msgid "This product is currently not available."
msgid "Hide product if unavailable"
msgstr "Nascondi il prodotto se non è disponibile"
msgstr "Questo prodotto non è al momento disponibile."
#: pretix/base/models/items.py:445
#: pretix/control/templates/pretixcontrol/subevents/fragment_unavail_mode_indicator.html:5
@@ -5337,23 +5339,26 @@ msgstr ""
#: pretix/base/models/items.py:1720 pretix/base/models/items.py:1726
#: pretix/base/models/items.py:1732
msgid "Minimum value"
msgstr "Valore minimo"
msgstr ""
#: pretix/base/models/items.py:1721 pretix/base/models/items.py:1724
#: pretix/base/models/items.py:1727 pretix/base/models/items.py:1730
#: pretix/base/models/items.py:1733 pretix/base/models/items.py:1736
#: pretix/base/models/items.py:1740
#, fuzzy
msgid "Currently not supported in our apps and during check-in"
msgstr "Attualmente non è supportato nelle nostre app e durante il check-in"
msgstr "La domanda non può dipendere da una domanda fatta durante il check-in."
#: pretix/base/models/items.py:1723 pretix/base/models/items.py:1729
#: pretix/base/models/items.py:1735
#, fuzzy
msgid "Maximum value"
msgstr "Valore massimo"
msgstr "Tasse"
#: pretix/base/models/items.py:1738
#, fuzzy
msgid "Maximum length"
msgstr "Lunghezza massima"
msgstr "Tasse"
#: pretix/base/models/items.py:1744
msgid "Validate file to be a portrait"
@@ -5367,7 +5372,7 @@ msgstr ""
#: pretix/base/models/items.py:1800
msgid "An answer to this question is required to proceed."
msgstr "Per procedere è necessario rispondere a questa domanda."
msgstr ""
#: pretix/base/models/items.py:1810
#, fuzzy
@@ -5376,23 +5381,25 @@ msgstr "oggetto non valido"
#: pretix/base/models/items.py:1844
msgid "The number is to low."
msgstr "Il numero è troppo basso."
msgstr ""
#: pretix/base/models/items.py:1846
msgid "The number is to high."
msgstr "Il numero è troppo alto."
msgstr ""
#: pretix/base/models/items.py:1849
msgid "Invalid number input."
msgstr ""
#: pretix/base/models/items.py:1856 pretix/base/models/items.py:1880
#, fuzzy
msgid "Please choose a later date."
msgstr "Si prega di scegliere una data successiva."
msgstr "Data di Inizio"
#: pretix/base/models/items.py:1858 pretix/base/models/items.py:1882
#, fuzzy
msgid "Please choose an earlier date."
msgstr "Si prega di scegliere una data precedente."
msgstr "Data di Inizio"
#: pretix/base/models/items.py:1861
msgid "Invalid date input."
@@ -5408,12 +5415,12 @@ msgstr ""
#: pretix/base/models/items.py:1889
msgid "Unknown country code."
msgstr "Codice del paese sconosciuto."
msgstr ""
#: pretix/base/models/items.py:1919
#: pretix/control/templates/pretixcontrol/items/question.html:90
msgid "Answer"
msgstr "Risposta"
msgstr ""
#: pretix/base/models/items.py:1943
msgid "The identifier \"{}\" is already used for a different option."
@@ -19436,7 +19443,7 @@ msgstr "Conteggio"
#: pretix/control/templates/pretixcontrol/items/question.html:92
msgid "Percentage"
msgstr "Percentuale"
msgstr ""
#: pretix/control/templates/pretixcontrol/items/question.html:110
#: pretix/control/templates/pretixcontrol/order/transactions.html:65
File diff suppressed because it is too large Load Diff
+67 -51
View File
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-29 08:53+0000\n"
"PO-Revision-Date: 2024-10-29 21:00+0000\n"
"PO-Revision-Date: 2024-09-27 18:00+0000\n"
"Last-Translator: Anarion Dunedain <anarion80@gmail.com>\n"
"Language-Team: Polish <https://translate.pretix.eu/projects/pretix/pretix/pl/"
">\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 5.8.1\n"
"X-Generator: Weblate 5.7.2\n"
#: pretix/_base_settings.py:79
msgid "English"
@@ -4606,40 +4606,43 @@ msgstr ""
#: pretix/base/models/items.py:114 pretix/base/models/items.py:159
#: pretix/control/forms/item.py:99
#, fuzzy
#| msgid "No category"
msgid "Normal category"
msgstr "Normalna kategoria"
msgstr "Brak kategorii"
#: pretix/base/models/items.py:115 pretix/control/forms/item.py:112
msgid "Normal + cross-selling category"
msgstr "Normalna + sprzedaż krzyżowa"
msgstr ""
#: pretix/base/models/items.py:116 pretix/control/forms/item.py:107
#, fuzzy
#| msgid "No category"
msgid "Cross-selling category"
msgstr "Kategoria sprzedaży krzyżowej"
msgstr "Brak kategorii"
#: pretix/base/models/items.py:124
msgid "Always show in cross-selling step"
msgstr "Zawsze pokazuj w kroku sprzedaży krzyżowej"
msgstr ""
#: pretix/base/models/items.py:125
msgid ""
"Only show products that qualify for a discount according to discount rules"
msgstr ""
"Pokaż tylko produkty kwalifikujące się do zniżki zgodnie z zasadami "
"rabatowymi"
#: pretix/base/models/items.py:126
msgid "Only show if the cart contains one of the following products"
msgstr ""
"Pokaż tylko, jeśli w koszyku znajduje się jeden z następujących produktów"
#: pretix/base/models/items.py:129
msgid "Cross-selling condition"
msgstr "Warunek sprzedaży krzyżowej"
msgstr ""
#: pretix/base/models/items.py:137
#, fuzzy
#| msgid "Count add-on products"
msgid "Cross-selling condition products"
msgstr "Produkty warunkowej sprzedaży krzyżowej"
msgstr "Policz produkty dodatkowe"
#: pretix/base/models/items.py:143
#: pretix/control/templates/pretixcontrol/items/categories.html:3
@@ -4651,11 +4654,13 @@ msgstr "Kategorie produktów"
#: pretix/base/models/items.py:149
#, python-brace-format
msgid "{category} ({category_type})"
msgstr "{category} ({category_type})"
msgstr ""
#: pretix/base/models/items.py:155
#, fuzzy
#| msgid "No category"
msgid "Add-on category"
msgstr "Kategoria dodatków"
msgstr "Brak kategorii"
#: pretix/base/models/items.py:222 pretix/base/models/items.py:278
msgid "Disable product for this date"
@@ -6018,8 +6023,10 @@ msgid "Ticket"
msgstr "Bilet"
#: pretix/base/models/orders.py:3405
#, fuzzy
#| msgid "Verification"
msgid "Certificate"
msgstr "Certyfikat"
msgstr "Weryfikacja"
#: pretix/base/models/orders.py:3406 pretix/control/views/event.py:367
#: pretix/control/views/event.py:372
@@ -6185,13 +6192,11 @@ msgstr ""
#, python-brace-format
msgid "Seat with zone {zone}, row {row}, and number {number} has no seat ID."
msgstr ""
"Miejsce w strefie {zone}, rzędzie {row} i numerze {number} nie ma "
"identyfikatora miejsca."
#: pretix/base/models/seating.py:71
#, python-brace-format
msgid "Multiple seats have the same ID: {id}"
msgstr "Wiele miejsc ma ten sam identyfikator: {id}"
msgstr ""
#: pretix/base/models/seating.py:199
#, python-brace-format
@@ -9039,8 +9044,10 @@ msgid "Ask for beneficiary"
msgstr "Zapytaj o beneficjenta"
#: pretix/base/settings.py:574
#, fuzzy
#| msgid "Custom recipient field"
msgid "Custom recipient field label"
msgstr "Etykieta pola niestandardowego odbiorcy"
msgstr "Niestandardowe pole odbiorcy"
#: pretix/base/settings.py:576
msgid ""
@@ -9057,8 +9064,10 @@ msgstr ""
"ona wyświetlana na fakturze poniżej nagłówka. Pole nie będzie wymagane."
#: pretix/base/settings.py:589
#, fuzzy
#| msgid "Custom recipient field"
msgid "Custom recipient field help text"
msgstr "Tekst pomocy dotyczący pola odbiorcy niestandardowego"
msgstr "Niestandardowe pole odbiorcy"
#: pretix/base/settings.py:591
msgid ""
@@ -9066,8 +9075,6 @@ msgid ""
"will be displayed underneath the field. It will not be displayed on the "
"invoice."
msgstr ""
"Jeśli używasz niestandardowego pola odbiorcy, możesz określić tekst pomocy, "
"który będzie wyświetlany pod polem. Nie będzie on wyświetlany na fakturze."
#: pretix/base/settings.py:601
msgid "Ask for VAT ID"
@@ -12505,9 +12512,12 @@ msgstr ""
"zakończenia przedsprzedaży"
#: pretix/base/timeline.py:106
#, fuzzy
#| msgctxt "timeline"
#| msgid "Customers can no longer modify their orders"
msgctxt "timeline"
msgid "Customers can no longer modify their order information"
msgstr "Klienci nie mogą już modyfikować swojego zamówienia"
msgstr "Klienci nie mogą już modyfikować swoich zamówień"
#: pretix/base/timeline.py:119
msgctxt "timeline"
@@ -12530,6 +12540,9 @@ msgid "Customers can no longer cancel paid orders"
msgstr "Klienci nie mogą już anulować opłaconych zamówień"
#: pretix/base/timeline.py:167
#, fuzzy
#| msgctxt "timeline"
#| msgid "Customers can no longer modify their orders"
msgctxt "timeline"
msgid "Customers can no longer make changes to their orders"
msgstr "Klienci nie mogą już modyfikować swoich zamówień"
@@ -14075,30 +14088,31 @@ msgstr ""
"wtyczki. Będzie on publicznie dostępny. Upewnij się, że jest on aktualny!"
#: pretix/control/forms/item.py:100
#, fuzzy
#| msgid "Products in this category are add-on products"
msgid ""
"Products in this category are regular products displayed on the front page."
msgstr ""
"Produkty w tej kategorii to zwykłe produkty wyświetlane na stronie głównej."
msgstr "Produkty w tej kategorii są dodatkami"
#: pretix/control/forms/item.py:103
#, fuzzy
#| msgid "Product category"
msgid "Add-on product category"
msgstr "Kategoria produktu dodatkowego"
msgstr "Kategoria produku"
#: pretix/control/forms/item.py:104
#, fuzzy
#| msgid "Products in this category are add-on products"
msgid ""
"Products in this category are add-on products and can only be bought as add-"
"ons."
msgstr ""
"Produkty w tej kategorii są produktami dodatkowymi i można je kupić "
"wyłącznie jako dodatki."
msgstr "Produkty w tej kategorii są dodatkami"
#: pretix/control/forms/item.py:108
msgid ""
"Products in this category are regular products, but are only shown in the "
"cross-selling step, according to the configuration below."
msgstr ""
"Produkty w tej kategorii to zwykłe produkty, ale są wyświetlane tylko na "
"etapie sprzedaży krzyżowej, zgodnie z konfiguracją poniżej."
#: pretix/control/forms/item.py:113
msgid ""
@@ -14106,9 +14120,6 @@ msgid ""
"but are additionally shown in the cross-selling step, according to the "
"configuration below."
msgstr ""
"Produkty w tej kategorii to zwykłe produkty wyświetlane na stronie głównej, "
"ale są dodatkowo pokazywane na etapie sprzedaży krzyżowej, zgodnie z "
"poniższą konfiguracją."
#: pretix/control/forms/item.py:141 pretix/control/forms/item.py:211
msgid "This field is required"
@@ -16526,9 +16537,12 @@ msgid "The check-in of position #{posid} on list \"{list}\" has been reverted."
msgstr "Zameldowanie pozycji #{posid} na liście \"{list}\" zostało cofnięte."
#: pretix/control/logdisplay.py:644
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid ""
#| "Position #{posid} has been checked in at {datetime} for list \"{list}\"."
msgid "Position #{posid} has been printed at {datetime} with type \"{type}\"."
msgstr "Pozycja #{posid} została wydrukowana o {datetime} z typem „{type}”."
msgstr ""
"Pozycja #{posid} została zameldowana w {datetime} dla listy \"{list}\"."
#: pretix/control/logdisplay.py:667
#, python-brace-format
@@ -17214,9 +17228,6 @@ msgid ""
"check that you have completed all installation steps and your cronjob is "
"executed correctly."
msgstr ""
"Komponent cronjob pretix nie został uruchomiony w ciągu ostatnich godzin. "
"Sprawdź, czy ukończyłeś wszystkie kroki instalacji i czy twój cronjob został "
"wykonany poprawnie."
#: pretix/control/templates/pretixcontrol/base.html:435
msgid ""
@@ -20068,8 +20079,10 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/item/base.html:24
#: pretix/control/templates/pretixcontrol/item/include_variations.html:79
#, fuzzy
#| msgid "Manage questions"
msgid "Manage quotas"
msgstr "Zarządzaj pulami"
msgstr "Zarządzaj pytaniami"
#: pretix/control/templates/pretixcontrol/item/base.html:27
#: pretix/control/templates/pretixcontrol/item/include_variations.html:82
@@ -20442,8 +20455,10 @@ msgid "Create a new category"
msgstr "Utwórz nową kategorię"
#: pretix/control/templates/pretixcontrol/items/categories.html:34
#, fuzzy
#| msgid "Category name"
msgid "Category type"
msgstr "Typ kategorii"
msgstr "Nazwa kategorii"
#: pretix/control/templates/pretixcontrol/items/categories.html:48
#: pretix/control/templates/pretixcontrol/items/discounts.html:138
@@ -25377,8 +25392,6 @@ msgid ""
"According to your event settings, sold out products are hidden from "
"customers. This way, customers will not be able to discover the waiting list."
msgstr ""
"Zgodnie z ustawieniami wydarzenia, wyprzedane produkty są ukryte przed "
"klientami. W ten sposób klienci nie będą mogli znaleźć listy oczekujących."
#: pretix/control/templates/pretixcontrol/waitinglist/index.html:36
msgid "Send vouchers"
@@ -31806,25 +31819,28 @@ msgid ""
"A product in your cart is only sold in combination with add-on products that "
"are no longer available. Please contact the event organizer."
msgstr ""
"Produkt w Twoim koszyku jest sprzedawany tylko w połączeniu z produktami "
"dodatkowymi, które nie są już dostępne. Skontaktuj się z organizatorem "
"wydarzenia."
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:20
msgid "We're now trying to book these add-ons for you!"
msgstr "Staramy się teraz zarezerwować te dodatki dla Ciebie!"
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:28
#, fuzzy
#| msgid "Additional settings"
msgid "Additional options for"
msgstr "Dodatkowe opcje dla"
msgstr "Dodatkowe ustawienia"
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:64
#, fuzzy
#| msgid "Top recommendation"
msgid "More recommendations"
msgstr "Więcej rekomendacji"
msgstr "Najlepsza rekomendacja"
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:71
#, fuzzy
#| msgid "Top recommendation"
msgid "Our recommendations"
msgstr "Nasze rekomendacje"
msgstr "Najlepsza rekomendacja"
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:89
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:201
@@ -32830,8 +32846,10 @@ msgid "Payment pending"
msgstr "W toku płatności"
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:19
#, fuzzy
#| msgid "Your orders for {event}"
msgid "Your order qualifies for a discount"
msgstr "Twoje zamówienia kwalifikuje się do zniżki"
msgstr "Twoje zamówienia na {event}"
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:28
#: pretix/presale/templates/pretixpresale/event/voucher.html:78
@@ -34372,8 +34390,6 @@ msgid ""
"No ticket types are available for the waiting list, have a look at the "
"ticket shop instead."
msgstr ""
"Nie ma dostępnych typów biletów dla listy oczekujących, zamiast tego należy "
"udać się do sklepu z biletami."
#: pretix/presale/views/waiting.py:137 pretix/presale/views/waiting.py:161
msgid "Waiting lists are disabled for this event."
+4 -4
View File
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-29 08:53+0000\n"
"PO-Revision-Date: 2024-10-30 19:00+0000\n"
"PO-Revision-Date: 2024-09-18 14:02+0000\n"
"Last-Translator: Tinna Sandström <tinna@coeo.events>\n"
"Language-Team: Swedish <https://translate.pretix.eu/projects/pretix/pretix/"
"sv/>\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.8.1\n"
"X-Generator: Weblate 5.7.2\n"
#: pretix/_base_settings.py:79
msgid "English"
@@ -22131,7 +22131,7 @@ msgid ""
"After starting this operation, depending on the size of your event, it might "
"take a few minutes or longer until all orders are processed."
msgstr ""
"Efter att du har startat denna process kan det, beroende på storleken på "
"Efter att du har startat denna operation kan det, beroende på storleken på "
"ditt evenemang, ta några minuter eller längre tid innan alla bokningar är "
"behandlade."
@@ -31866,7 +31866,7 @@ msgstr "Ändra kontaktinformation"
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:167
msgid "Confirmations"
msgstr "Villkor"
msgstr "Bekräftelser"
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:185
msgid ""
+1 -2
View File
@@ -21,7 +21,6 @@
#
from django import forms
from django.conf import settings
from django.utils.translation import pgettext
from i18nfield.strings import LazyI18nString
from pretix.base.models import EventMetaValue, SubEventMetaValue
@@ -67,7 +66,7 @@ def meta_filtersets(organizer, event=None):
).values_list("value", flat=True).distinct())
choices = [(k, k) for k in sorted(existing_values)]
choices.insert(0, ("", "-- %s --" % pgettext("filter_empty", "all")))
choices.insert(0, ("", ""))
if len(choices) > 1:
fields[f"attr[{prop.name}]"] = {
"label": str(prop.public_label) or prop.name,
+1456 -1079
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -4,8 +4,8 @@
"private": true,
"scripts": {},
"dependencies": {
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^15.3.0",
"vue": "^2.7.16",
@@ -378,7 +378,6 @@ var form_handlers = function (el) {
dependency = findDependency($(this).attr("data-display-dependency"), this),
update = function (ev) {
var enabled = dependency.toArray().some(function(d) {
if (d.disabled) return false;
if (d.type === 'checkbox' || d.type === 'radio') {
return d.checked;
} else if (d.type === 'select-one') {
@@ -399,7 +398,7 @@ var form_handlers = function (el) {
}
var $toggling = dependent;
if (dependent.attr("data-disable-dependent")) {
$toggling.attr('disabled', !enabled).trigger("change");
$toggling.attr('disabled', !enabled);
}
if (dependent.get(0).tagName.toLowerCase() !== "div") {
$toggling = dependent.closest('.form-group');
+1 -1
View File
@@ -40,7 +40,7 @@ def mocker_context():
def get_redis_connection(alias="default", write=True):
worker_id = os.environ.get("PYTEST_XDIST_WORKER")
if worker_id and worker_id.startswith("gw"):
if worker_id.startswith("gw"):
redis_port = 1000 + int(worker_id.replace("gw", ""))
else:
redis_port = 1000
+39 -1
View File
@@ -252,8 +252,9 @@ def test_list_list(token_client, organizer, event, clist, item, subevent, django
res = dict(TEST_LIST_RES)
res["id"] = clist.pk
res["limit_products"] = [item.pk]
res["auto_checkin_sales_channels"] = []
with django_assert_num_queries(11):
with django_assert_num_queries(12):
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
assert [res] == resp.data['results']
@@ -291,6 +292,7 @@ def test_list_detail(token_client, organizer, event, clist, item):
res["id"] = clist.pk
res["limit_products"] = [item.pk]
res["auto_checkin_sales_channels"] = []
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/'.format(organizer.slug, event.slug,
clist.pk))
assert resp.status_code == 200
@@ -325,6 +327,9 @@ def test_list_create(token_client, organizer, event, item, item_on_wrong_event):
"limit_products": [item.pk],
"all_products": False,
"subevent": None,
"auto_checkin_sales_channels": [
"web"
]
},
format='json'
)
@@ -334,6 +339,7 @@ def test_list_create(token_client, organizer, event, item, item_on_wrong_event):
assert cl.name == "VIP"
assert cl.limit_products.count() == 1
assert not cl.all_products
assert cl.auto_checkin_sales_channels.filter(identifier="web").exists()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
@@ -363,6 +369,24 @@ def test_list_create_with_subevent(token_client, organizer, event, event3, item,
)
assert resp.status_code == 201
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
"name": "VIP",
"limit_products": [item.pk],
"all_products": True,
"subevent": subevent.pk,
"auto_checkin_sales_channels": [
"web"
]
},
format='json'
)
assert resp.status_code == 201
with scopes_disabled():
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.auto_checkin_sales_channels.filter(identifier="web").exists()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
{
@@ -416,6 +440,20 @@ def test_list_update(token_client, organizer, event, clist):
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/checkinlists/{}/'.format(organizer.slug, event.slug, clist.pk),
{
"auto_checkin_sales_channels": [
"web"
],
},
format='json'
)
assert resp.status_code == 200
with scopes_disabled():
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.auto_checkin_sales_channels.filter(identifier="web").exists()
@pytest.mark.django_db
def test_list_all_items_positions(token_client, organizer, event, clist, clist_all, item, other_item, order, django_assert_num_queries):
+37 -1
View File
@@ -165,6 +165,13 @@ def order(event, item, taxrule, question):
return o
@pytest.fixture
def clist_autocheckin(event):
c = event.checkin_lists.create(name="Default", all_products=True)
c.auto_checkin_sales_channels.add(event.organizer.sales_channels.get(identifier="web"))
return c
ORDER_CREATE_PAYLOAD = {
"email": "dummy@dummy.test",
"phone": "+49622112345",
@@ -485,7 +492,6 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
'refunds': [],
'require_approval': False,
'sales_channel': 'web',
'cancellation_date': None
}
@@ -541,6 +547,36 @@ def test_order_create_positionids_addons_simulated(token_client, organizer, even
]
@pytest.mark.django_db
def test_order_create_autocheckin(token_client, organizer, event, item, quota, question, clist_autocheckin):
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
res['positions'][0]['item'] = item.pk
res['positions'][0]['answers'][0]['question'] = question.pk
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/'.format(
organizer.slug, event.slug
), format='json', data=res
)
assert resp.status_code == 201
with scopes_disabled():
o = Order.objects.get(code=resp.data['code'])
assert clist_autocheckin.auto_checkin_sales_channels.contains(organizer.sales_channels.get(identifier="web"))
assert o.positions.first().checkins.first().auto_checked_in
clist_autocheckin.auto_checkin_sales_channels.clear()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/'.format(
organizer.slug, event.slug
), format='json', data=res
)
assert resp.status_code == 201
with scopes_disabled():
o = Order.objects.get(code=resp.data['code'])
assert clist_autocheckin.auto_checkin_sales_channels.count() == 0
assert o.positions.first().checkins.count() == 0
@pytest.mark.django_db
def test_order_create_require_approval_free(token_client, organizer, event, item, quota, question):
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
+7 -1
View File
@@ -180,6 +180,13 @@ def order2(event2, item2):
return o
@pytest.fixture
def clist_autocheckin(event):
c = event.checkin_lists.create(name="Default", all_products=True)
c.auto_checkin_sales_channels.add(event.organizer.sales_channels.get(identifier="web"))
return c
TEST_ORDERPOSITION_RES = {
"id": 1,
"order": "FOO",
@@ -330,7 +337,6 @@ TEST_ORDER_RES = {
"downloads": [],
"payments": TEST_PAYMENTS_RES,
"refunds": TEST_REFUNDS_RES,
"cancellation_date": None,
}
+8
View File
@@ -126,6 +126,7 @@ def test_full_clone_same_organizer():
],
})
clist.limit_products.add(item1)
clist.auto_checkin_sales_channels.add(sc)
copied_event = Event.objects.create(
organizer=organizer, name='Dummy2', slug='dummy2',
@@ -211,6 +212,7 @@ def test_full_clone_same_organizer():
],
}
assert copied_clist.limit_products.get() == copied_item1
assert copied_clist.auto_checkin_sales_channels.get() == sc
# todo: test that the plugin hook is called
# todo: test custom style
@@ -246,6 +248,9 @@ def test_full_clone_cross_organizer_differences():
item2 = event.items.create(name="T-shirt", default_price=15)
item2.require_membership_types.add(membership_type)
clist = event.checkin_lists.create(name="Default")
clist.auto_checkin_sales_channels.add(sc)
copied_event = Event.objects.create(
organizer=organizer2, name='Dummy2', slug='dummy2',
date_from=datetime.datetime(2022, 4, 15, 9, 0, 0, tzinfo=datetime.timezone.utc),
@@ -265,3 +270,6 @@ def test_full_clone_cross_organizer_differences():
assert copied_item1.grant_membership_type is None
assert copied_item2.require_membership_types.count() == 0
assert copied_item1.limit_sales_channels.get() == sc2
copied_clist = copied_event.checkin_lists.get()
assert copied_clist.auto_checkin_sales_channels.get() == sc2
+54
View File
@@ -71,6 +71,13 @@ def event():
yield event
@pytest.fixture
def clist_autocheckin(event):
c = event.checkin_lists.create(name="Default", all_products=True)
c.auto_checkin_sales_channels.add(event.organizer.sales_channels.get(identifier="web"))
return c
@pytest.mark.django_db
def test_expiry_days(event):
today = now()
@@ -3451,6 +3458,53 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.valid_until is None
@pytest.mark.django_db
def test_autocheckin(clist_autocheckin, event):
today = now()
tr7 = event.tax_rules.create(rate=Decimal('17.00'))
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rule=tr7,
default_price=Decimal('23.00'), admission=True)
cp1 = CartPosition.objects.create(
item=ticket, price=23, expires=now() + timedelta(days=1), event=event, cart_id="123"
)
order = _create_order(event, email='dummy@example.org', positions=[cp1],
now_dt=today,
sales_channel=event.organizer.sales_channels.get(identifier="web"),
payment_requests=[{
"id": "test0",
"provider": "free",
"max_value": None,
"min_value": None,
"multi_use_supported": False,
"info_data": {},
"pprov": FreeOrderProvider(event),
}],
locale='de')[0]
assert clist_autocheckin.auto_checkin_sales_channels.contains(event.organizer.sales_channels.get(identifier="web"))
assert order.positions.first().checkins.first().auto_checked_in
clist_autocheckin.auto_checkin_sales_channels.clear()
cp1 = CartPosition.objects.create(
item=ticket, price=23, expires=now() + timedelta(days=1), event=event, cart_id="123"
)
order = _create_order(event, email='dummy@example.org', positions=[cp1],
now_dt=today,
sales_channel=event.organizer.sales_channels.get(identifier="web"),
payment_requests=[{
"id": "test0",
"provider": "free",
"max_value": None,
"min_value": None,
"multi_use_supported": False,
"info_data": {},
"pprov": FreeOrderProvider(event),
}],
locale='de')[0]
assert clist_autocheckin.auto_checkin_sales_channels.count() == 0
assert order.positions.first().checkins.count() == 0
@pytest.mark.django_db
def test_saleschannel_testmode_restriction(event):
today = now()
+1 -4
View File
@@ -228,7 +228,6 @@ def checkin_list_env():
# checkin
Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1), list=cl)
Checkin.objects.create(position=op_a3_ticket, list=cl)
Checkin.objects.create(position=op_a3_ticket, list=cl, type="exit")
return event, user, orga, [item_ticket, item_mascot], [order_pending, order_a1, order_a2, order_a3], \
[op_pending_ticket, op_a1_ticket, op_a1_mascot, op_a2_ticket, op_a3_ticket], cl
@@ -261,10 +260,8 @@ def test_checkins_list_ordering(client, checkin_list_env, order_key, expected):
@pytest.mark.django_db
@pytest.mark.parametrize("query, expected", [
('status=&item=&user=', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
('status=0&item=&user=', ['A1Mascot', 'A2Ticket']),
('status=1&item=&user=', ['A1Ticket', 'A3Ticket']),
('status=2&item=&user=', ['A1Ticket']),
('status=3&item=&user=', ['A3Ticket']),
('status=0&item=&user=', ['A1Mascot', 'A2Ticket']),
('status=&item=&user=a3dummy', ['A3Ticket']), # match order email
('status=&item=&user=a3dummy', ['A3Ticket']), # match order email,
('status=&item=&user=a4', ['A3Ticket']), # match attendee name
+43 -111
View File
@@ -1309,14 +1309,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-itemvar'.format(self.op1.pk): str(self.shirt.pk),
'op-{}-price'.format(self.op1.pk): str('12.00'),
})
@@ -1345,14 +1341,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-subevent'.format(self.op1.pk): str(se2.pk),
})
self.op1.refresh_from_db()
@@ -1381,14 +1373,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-used_membership'.format(self.op1.pk): str(m_correct1.pk),
'op-{}-used_membership'.format(self.op2.pk): str(m_correct1.pk),
'op-{}-used_membership'.format(self.op3.pk): str(m_correct1.pk),
@@ -1401,14 +1389,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-operation'.format(self.op1.pk): 'price',
'op-{}-itemvar'.format(self.op1.pk): str(self.ticket.pk),
'op-{}-price'.format(self.op1.pk): '24.00',
@@ -1425,14 +1409,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-operation_cancel'.format(self.op1.pk): 'on',
})
self.order.refresh_from_db()
@@ -1444,17 +1424,13 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '1',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add_position-0-itemvar': str(self.shirt.pk),
'add_position-0-do': 'on',
'add_position-0-price': '14.00',
'add-TOTAL_FORMS': '1',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'add-0-itemvar': str(self.shirt.pk),
'add-0-do': 'on',
'add-0-price': '14.00',
})
with scopes_disabled():
assert self.order.positions.count() == 3
@@ -1477,14 +1453,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'other-recalculate_taxes': 'net',
'op-{}-operation'.format(self.op1.pk): '',
'op-{}-operation'.format(self.op2.pk): '',
@@ -1517,14 +1489,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'other-recalculate_taxes': 'gross',
'op-{}-operation'.format(self.op1.pk): '',
'op-{}-operation'.format(self.op2.pk): '',
@@ -1549,14 +1517,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-price'.format(self.op1.pk): '24.00',
'op-{}-operation'.format(self.op2.pk): '',
'op-{}-itemvar'.format(self.op2.pk): str(self.ticket.pk),
@@ -1580,14 +1544,10 @@ class OrderChangeTests(SoupTest):
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '0',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add-TOTAL_FORMS': '0',
'add-INITIAL_FORMS': '0',
'add-MIN_NUM_FORMS': '0',
'add-MAX_NUM_FORMS': '100',
'op-{}-operation'.format(self.op1.pk): 'price',
'op-{}-itemvar'.format(self.op1.pk): str(self.ticket.pk),
'op-{}-price'.format(self.op1.pk): '24.00',
@@ -1603,34 +1563,6 @@ class OrderChangeTests(SoupTest):
self.op2.refresh_from_db()
assert self.order.total == self.op1.price + self.op2.price
def test_add_fee_success(self):
old_total = self.order.total
r = self.client.post('/control/event/{}/{}/orders/{}/change'.format(
self.event.organizer.slug, self.event.slug, self.order.code
), {
'add_fee-TOTAL_FORMS': '1',
'add_fee-INITIAL_FORMS': '0',
'add_fee-MIN_NUM_FORMS': '0',
'add_fee-MAX_NUM_FORMS': '100',
'add_position-TOTAL_FORMS': '0',
'add_position-INITIAL_FORMS': '0',
'add_position-MIN_NUM_FORMS': '0',
'add_position-MAX_NUM_FORMS': '100',
'add_fee-0-do': 'on',
'add_fee-0-fee_type': 'other',
'add_fee-0-description': 'Surprise Fee',
'add_fee-0-value': '5.00',
})
assert r.status_code == 302
self.order.refresh_from_db()
with scopes_disabled():
fee = self.order.fees.get()
assert fee.fee_type == OrderFee.FEE_TYPE_OTHER
assert fee.description == 'Surprise Fee'
assert fee.value == Decimal('5.00')
assert not fee.canceled
assert self.order.total == old_total + 5
@pytest.mark.django_db
def test_check_vatid(client, env):
+10 -10
View File
@@ -405,11 +405,11 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
SubEventItem.objects.create(subevent=se1, item=item, price=12)
resp = self.client.get('/%s/%s/%d/' % (self.orga.slug, self.event.slug, se1.pk))
self.assertIn("€12.00", resp.rendered_content)
self.assertNotIn("€15.00", resp.rendered_content)
self.assertIn("12.00", resp.rendered_content)
self.assertNotIn("15.00", resp.rendered_content)
resp = self.client.get('/%s/%s/%d/' % (self.orga.slug, self.event.slug, se2.pk))
self.assertIn("€15.00", resp.rendered_content)
self.assertNotIn("€12.00", resp.rendered_content)
self.assertIn("15.00", resp.rendered_content)
self.assertNotIn("12.00", resp.rendered_content)
def test_subevent_net_prices(self):
self.event.has_subevents = True
@@ -429,14 +429,14 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
resp = self.client.get('/%s/%s/%d/' % (self.orga.slug, self.event.slug, se1.pk))
doc = BeautifulSoup(resp.rendered_content, "lxml")
self.assertIn("€10.08", doc.text)
self.assertNotIn("€12.00", doc.text)
self.assertNotIn("€15.00", doc.text)
self.assertIn("10.08", doc.text)
self.assertNotIn("12.00", doc.text)
self.assertNotIn("15.00", doc.text)
resp = self.client.get('/%s/%s/%d/' % (self.orga.slug, self.event.slug, se2.pk))
doc = BeautifulSoup(resp.rendered_content, "lxml")
self.assertIn("€12.61", doc.text)
self.assertNotIn("€12.00", doc.text)
self.assertNotIn("€15.00", doc.text)
self.assertIn("12.61", doc.text)
self.assertNotIn("12.00", doc.text)
self.assertNotIn("15.00", doc.text)
def test_variations_subevent_disabled(self):
self.event.has_subevents = True
+3 -3
View File
@@ -812,7 +812,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", "-- all --"], ["EN", "English"], ["DE", "German"]],
"choices": [["", ""], ["EN", "English"], ["DE", "German"]],
"key": "attr[Language]",
"label": "Language"
}
@@ -838,7 +838,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", "-- all --"], ["DE", "DE"], ["EN", "EN"]],
"choices": [["", ""], ["DE", "DE"], ["EN", "EN"]],
"key": "attr[Language]",
"label": "Language"
}
@@ -848,7 +848,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", "-- all --"], ["DE", "DE"]],
"choices": [["", ""], ["DE", "DE"]],
"key": "attr[Language]",
"label": "Language"
}