Compare commits

..

4 Commits

Author SHA1 Message Date
Mira
2cb7160ed7 Add documentation 2025-04-29 15:28:33 +02:00
Mira
7575a6f0d1 Event list: fix parsing of date query parameter
Use the same localization formats as used when generating the value
2025-04-28 20:00:58 +02:00
Mira
4c6bd30437 Revert "Event list: Use standards-compliant date format for <input type="date">"
This reverts commit 6bd34c79ee.
2025-04-28 19:59:47 +02:00
luelista
6bd34c79ee Event list: Use standards-compliant date format for <input type="date"> 2025-04-28 17:24:28 +02:00
35 changed files with 1374 additions and 1569 deletions

View File

@@ -87,11 +87,11 @@ dependencies = [
"pytz",
"pytz-deprecation-shim==0.1.*",
"pyuca",
"qrcode==8.2",
"qrcode==8.1",
"redis==5.2.*",
"reportlab==4.4.*",
"reportlab==4.3.*",
"requests==2.31.*",
"sentry-sdk==2.27.*",
"sentry-sdk==2.25.*",
"sepaxml==2.6.*",
"stripe==7.9.*",
"text-unidecode==1.*",
@@ -114,7 +114,7 @@ dev = [
"flake8==7.2.*",
"freezegun",
"isort==6.0.*",
"pep8-naming==0.15.*",
"pep8-naming==0.14.*",
"potypo",
"pytest-asyncio>=0.24",
"pytest-cache",

View File

@@ -712,7 +712,7 @@ class OrderListExporter(MultiSheetListExporter):
if name_scheme and len(name_scheme['fields']) > 1:
for k, label, w in name_scheme['fields']:
row.append(
get_name_parts_localized(op.attendee_name_parts, k) if op.attendee_name_parts else ''
get_name_parts_localized(op.attendee_name_parts, k)
)
row += [
op.attendee_email,

View File

@@ -58,7 +58,6 @@ from django.urls import reverse
from django.utils.formats import date_format
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.text import format_lazy
from django.utils.timezone import get_current_timezone
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django_countries import countries
@@ -871,23 +870,6 @@ class BaseQuestionsForm(forms.Form):
attrs['data-min'] = q.valid_date_min.isoformat()
if q.valid_date_max:
attrs['data-max'] = q.valid_date_max.isoformat()
if not help_text:
if q.valid_date_min and q.valid_date_max:
help_text = format_lazy(
'Please enter a date between {min} and {max}.',
min=date_format(q.valid_date_min, "SHORT_DATE_FORMAT"),
max=date_format(q.valid_date_max, "SHORT_DATE_FORMAT"),
)
elif q.valid_date_min:
help_text = format_lazy(
'Please enter a date no earlier than {min}.',
min=date_format(q.valid_date_min, "SHORT_DATE_FORMAT"),
)
elif q.valid_date_max:
help_text = format_lazy(
'Please enter a date no later than {max}.',
max=date_format(q.valid_date_max, "SHORT_DATE_FORMAT"),
)
field = forms.DateField(
label=label, required=required,
help_text=help_text,
@@ -906,23 +888,6 @@ class BaseQuestionsForm(forms.Form):
widget=TimePickerWidget(time_format=get_format_without_seconds('TIME_INPUT_FORMATS')),
)
elif q.type == Question.TYPE_DATETIME:
if not help_text:
if q.valid_datetime_min and q.valid_datetime_max:
help_text = format_lazy(
'Please enter a date and time between {min} and {max}.',
min=date_format(q.valid_datetime_min, "SHORT_DATETIME_FORMAT"),
max=date_format(q.valid_datetime_max, "SHORT_DATETIME_FORMAT"),
)
elif q.valid_datetime_min:
help_text = format_lazy(
'Please enter a date and time no earlier than {min}.',
min=date_format(q.valid_datetime_min, "SHORT_DATETIME_FORMAT"),
)
elif q.valid_datetime_max:
help_text = format_lazy(
'Please enter a date and time no later than {max}.',
max=date_format(q.valid_datetime_max, "SHORT_DATETIME_FORMAT"),
)
field = SplitDateTimeField(
label=label, required=required,
help_text=help_text,

View File

@@ -1463,10 +1463,6 @@ class GiftCardPayment(BasePaymentProvider):
messages.error(request, _("You cannot pay with gift cards when buying a gift card."))
return
if not request.POST.get("giftcard"):
messages.error(request, _("Please enter the code of your gift card."))
return
try:
gc = self.event.organizer.accepted_gift_cards.get(
secret=request.POST.get("giftcard").strip()

View File

@@ -2221,79 +2221,73 @@ class OrderChangeManager:
nextposid = self.order.all_positions.aggregate(m=Max('positionid'))['m'] + 1
split_positions = []
secret_dirty = set()
position_cache = {}
fee_cache = {}
for op in self._operations:
if isinstance(op, self.ItemOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.item', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_item': position.item.pk,
'old_variation': position.variation.pk if position.variation else None,
'position': op.position.pk,
'positionid': op.position.positionid,
'old_item': op.position.item.pk,
'old_variation': op.position.variation.pk if op.position.variation else None,
'new_item': op.item.pk,
'new_variation': op.variation.pk if op.variation else None,
'old_price': position.price,
'addon_to': position.addon_to_id,
'new_price': position.price
'old_price': op.position.price,
'addon_to': op.position.addon_to_id,
'new_price': op.position.price
})
position.item = op.item
position.variation = op.variation
position._calculate_tax()
op.position.item = op.item
op.position.variation = op.variation
op.position._calculate_tax()
if position.voucher_budget_use is not None and position.voucher and not position.addon_to_id:
listed_price = get_listed_price(position.item, position.variation, position.subevent)
if not position.item.tax_rule or position.item.tax_rule.price_includes_tax:
price_after_voucher = max(position.price, position.voucher.calculate_price(listed_price))
if op.position.voucher_budget_use is not None and op.position.voucher and not op.position.addon_to_id:
listed_price = get_listed_price(op.position.item, op.position.variation, op.position.subevent)
if not op.position.item.tax_rule or op.position.item.tax_rule.price_includes_tax:
price_after_voucher = max(op.position.price, op.position.voucher.calculate_price(listed_price))
else:
price_after_voucher = max(position.price - position.tax_value, position.voucher.calculate_price(listed_price))
position.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
secret_dirty.add(position)
position.save()
price_after_voucher = max(op.position.price - op.position.tax_value, op.position.voucher.calculate_price(listed_price))
op.position.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
secret_dirty.add(op.position)
op.position.save()
elif isinstance(op, self.MembershipOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.membership', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_membership_id': position.used_membership_id,
'position': op.position.pk,
'positionid': op.position.positionid,
'old_membership_id': op.position.used_membership_id,
'new_membership_id': op.membership.pk if op.membership else None,
})
position.used_membership = op.membership
position.save()
op.position.used_membership = op.membership
op.position.save()
elif isinstance(op, self.SeatOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.seat', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_seat': position.seat.name if position.seat else "-",
'position': op.position.pk,
'positionid': op.position.positionid,
'old_seat': op.position.seat.name if op.position.seat else "-",
'new_seat': op.seat.name if op.seat else "-",
'old_seat_id': position.seat.pk if position.seat else None,
'old_seat_id': op.position.seat.pk if op.position.seat else None,
'new_seat_id': op.seat.pk if op.seat else None,
})
position.seat = op.seat
secret_dirty.add(position)
position.save()
op.position.seat = op.seat
secret_dirty.add(op.position)
op.position.save()
elif isinstance(op, self.SubeventOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.subevent', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_subevent': position.subevent.pk,
'position': op.position.pk,
'positionid': op.position.positionid,
'old_subevent': op.position.subevent.pk,
'new_subevent': op.subevent.pk,
'old_price': position.price,
'new_price': position.price
'old_price': op.position.price,
'new_price': op.position.price
})
position.subevent = op.subevent
secret_dirty.add(position)
if position.voucher_budget_use is not None and position.voucher and not position.addon_to_id:
listed_price = get_listed_price(position.item, position.variation, position.subevent)
if not position.item.tax_rule or position.item.tax_rule.price_includes_tax:
price_after_voucher = max(position.price, position.voucher.calculate_price(listed_price))
op.position.subevent = op.subevent
secret_dirty.add(op.position)
if op.position.voucher_budget_use is not None and op.position.voucher and not op.position.addon_to_id:
listed_price = get_listed_price(op.position.item, op.position.variation, op.position.subevent)
if not op.position.item.tax_rule or op.position.item.tax_rule.price_includes_tax:
price_after_voucher = max(op.position.price, op.position.voucher.calculate_price(listed_price))
else:
price_after_voucher = max(position.price - position.tax_value, position.voucher.calculate_price(listed_price))
position.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
position.save()
price_after_voucher = max(op.position.price - op.position.tax_value, op.position.voucher.calculate_price(listed_price))
op.position.voucher_budget_use = max(listed_price - price_after_voucher, Decimal('0.00'))
op.position.save()
elif isinstance(op, self.AddFeeOperation):
self.order.log_action('pretix.event.order.changed.addfee', user=self.user, auth=self.auth, data={
'fee': op.fee.pk,
@@ -2302,79 +2296,70 @@ class OrderChangeManager:
op.fee._calculate_tax()
op.fee.save()
elif isinstance(op, self.FeeValueOperation):
fee = fee_cache.setdefault(op.fee.pk, op.fee)
self.order.log_action('pretix.event.order.changed.feevalue', user=self.user, auth=self.auth, data={
'fee': fee.pk,
'old_price': fee.value,
'fee': op.fee.pk,
'old_price': op.fee.value,
'new_price': op.value.gross
})
fee.value = op.value.gross
fee._calculate_tax()
fee.save()
op.fee.value = op.value.gross
op.fee._calculate_tax()
op.fee.save()
elif isinstance(op, self.PriceOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.price', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_price': position.price,
'addon_to': position.addon_to_id,
'position': op.position.pk,
'positionid': op.position.positionid,
'old_price': op.position.price,
'addon_to': op.position.addon_to_id,
'new_price': op.price.gross
})
position.price = op.price.gross
position.tax_rate = op.price.rate
position.tax_value = op.price.tax
position.tax_code = op.price.code
position.save(update_fields=['price', 'tax_rate', 'tax_value', 'tax_code'])
op.position.price = op.price.gross
op.position.tax_rate = op.price.rate
op.position.tax_value = op.price.tax
op.position.tax_code = op.price.code
op.position.save(update_fields=['price', 'tax_rate', 'tax_value', 'tax_code'])
elif isinstance(op, self.TaxRuleOperation):
if isinstance(op.position, OrderPosition):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.tax_rule', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'addon_to': position.addon_to_id,
'old_taxrule': position.tax_rule.pk if position.tax_rule else None,
'position': op.position.pk,
'positionid': op.position.positionid,
'addon_to': op.position.addon_to_id,
'old_taxrule': op.position.tax_rule.pk if op.position.tax_rule else None,
'new_taxrule': op.tax_rule.pk
})
position._calculate_tax(op.tax_rule)
position.save()
elif isinstance(op.position, OrderFee):
fee = fee_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.tax_rule', user=self.user, auth=self.auth, data={
'fee': fee.pk,
'fee_type': fee.fee_type,
'old_taxrule': fee.tax_rule.pk if fee.tax_rule else None,
'fee': op.position.pk,
'fee_type': op.position.fee_type,
'old_taxrule': op.position.tax_rule.pk if op.position.tax_rule else None,
'new_taxrule': op.tax_rule.pk
})
fee._calculate_tax(op.tax_rule)
fee.save()
op.position._calculate_tax(op.tax_rule)
op.position.save()
elif isinstance(op, self.CancelFeeOperation):
fee = fee_cache.setdefault(op.fee.pk, op.fee)
self.order.log_action('pretix.event.order.changed.cancelfee', user=self.user, auth=self.auth, data={
'fee': fee.pk,
'fee_type': fee.fee_type,
'old_price': fee.value,
'fee': op.fee.pk,
'fee_type': op.fee.fee_type,
'old_price': op.fee.value,
})
fee.canceled = True
fee.save(update_fields=['canceled'])
op.fee.canceled = True
op.fee.save(update_fields=['canceled'])
elif isinstance(op, self.CancelOperation):
position = position_cache.setdefault(op.position.pk, op.position)
for gc in position.issued_gift_cards.all():
for gc in op.position.issued_gift_cards.all():
gc = GiftCard.objects.select_for_update(of=OF_SELF).get(pk=gc.pk)
if gc.value < position.price:
if gc.value < op.position.price:
raise OrderError(_(
'A position can not be canceled since the gift card {card} purchased in this order has '
'already been redeemed.').format(
card=gc.secret
))
else:
gc.transactions.create(value=-position.price, order=self.order, acceptor=self.order.event.organizer)
gc.transactions.create(value=-op.position.price, order=self.order, acceptor=self.order.event.organizer)
for m in position.granted_memberships.with_usages().all():
for m in op.position.granted_memberships.with_usages().all():
m.canceled = True
m.save()
for opa in position.addons.all():
opa = position_cache.setdefault(opa.pk, opa)
for opa in op.position.addons.all():
for gc in opa.issued_gift_cards.all():
gc = GiftCard.objects.select_for_update(of=OF_SELF).get(pk=gc.pk)
if gc.value < opa.position.price:
@@ -2408,22 +2393,22 @@ class OrderChangeManager:
)
opa.save(update_fields=['canceled', 'secret'])
self.order.log_action('pretix.event.order.changed.cancel', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'old_item': position.item.pk,
'old_variation': position.variation.pk if position.variation else None,
'old_price': position.price,
'position': op.position.pk,
'positionid': op.position.positionid,
'old_item': op.position.item.pk,
'old_variation': op.position.variation.pk if op.position.variation else None,
'old_price': op.position.price,
'addon_to': None,
})
position.canceled = True
if position.voucher:
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
op.position.canceled = True
if op.position.voucher:
Voucher.objects.filter(pk=op.position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
assign_ticket_secret(
event=self.event, position=position, force_invalidate_if_revokation_list_used=True, force_invalidate=False, save=False
event=self.event, position=op.position, force_invalidate_if_revokation_list_used=True, force_invalidate=False, save=False
)
if position in secret_dirty:
secret_dirty.remove(position)
position.save(update_fields=['canceled', 'secret'])
if op.position in secret_dirty:
secret_dirty.remove(op.position)
op.position.save(update_fields=['canceled', 'secret'])
elif isinstance(op, self.AddOperation):
pos = OrderPosition.objects.create(
item=op.item, variation=op.variation, addon_to=op.addon_to,
@@ -2448,22 +2433,20 @@ class OrderChangeManager:
'valid_until': op.valid_until.isoformat() if op.valid_until else None,
})
elif isinstance(op, self.SplitOperation):
position = position_cache.setdefault(op.position.pk, op.position)
split_positions.append(position)
split_positions.append(op.position)
elif isinstance(op, self.RegenerateSecretOperation):
position = position_cache.setdefault(op.position.pk, op.position)
position.web_secret = generate_secret()
position.save(update_fields=["web_secret"])
op.position.web_secret = generate_secret()
op.position.save(update_fields=["web_secret"])
assign_ticket_secret(
event=self.event, position=position, force_invalidate=True, save=True
event=self.event, position=op.position, force_invalidate=True, save=True
)
if position in secret_dirty:
secret_dirty.remove(position)
if op.position in secret_dirty:
secret_dirty.remove(op.position)
tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk,
'order': self.order.pk})
self.order.log_action('pretix.event.order.changed.secret', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'position': op.position.pk,
'positionid': op.position.positionid,
})
elif isinstance(op, self.ChangeSecretOperation):
if OrderPosition.all.filter(order__event=self.event, secret=op.new_secret).exists():
@@ -2479,68 +2462,64 @@ class OrderChangeManager:
'positionid': op.position.positionid,
})
elif isinstance(op, self.ChangeValidFromOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.valid_from', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'position': op.position.pk,
'positionid': op.position.positionid,
'new_value': op.valid_from.isoformat() if op.valid_from else None,
'old_value': position.valid_from.isoformat() if position.valid_from else None,
'old_value': op.position.valid_from.isoformat() if op.position.valid_from else None,
})
position.valid_from = op.valid_from
position.save(update_fields=['valid_from'])
secret_dirty.add(position)
op.position.valid_from = op.valid_from
op.position.save(update_fields=['valid_from'])
secret_dirty.add(op.position)
elif isinstance(op, self.ChangeValidUntilOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.valid_until', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'position': op.position.pk,
'positionid': op.position.positionid,
'new_value': op.valid_until.isoformat() if op.valid_until else None,
'old_value': position.valid_until.isoformat() if position.valid_until else None,
'old_value': op.position.valid_until.isoformat() if op.position.valid_until else None,
})
position.valid_until = op.valid_until
position.save(update_fields=['valid_until'])
secret_dirty.add(position)
op.position.valid_until = op.valid_until
op.position.save(update_fields=['valid_until'])
secret_dirty.add(op.position)
elif isinstance(op, self.AddBlockOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.add_block', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'position': op.position.pk,
'positionid': op.position.positionid,
'block_name': op.block_name,
})
if position.blocked:
if op.block_name not in position.blocked:
position.blocked = position.blocked + [op.block_name]
if op.position.blocked:
if op.block_name not in op.position.blocked:
op.position.blocked = op.position.blocked + [op.block_name]
else:
position.blocked = [op.block_name]
op.position.blocked = [op.block_name]
if op.ignore_from_quota_while_blocked is not None:
position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
if position.blocked:
position.blocked_secrets.update_or_create(
op.position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
op.position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
if op.position.blocked:
op.position.blocked_secrets.update_or_create(
event=self.event,
secret=position.secret,
secret=op.position.secret,
defaults={
'blocked': True,
'updated': now(),
}
)
elif isinstance(op, self.RemoveBlockOperation):
position = position_cache.setdefault(op.position.pk, op.position)
self.order.log_action('pretix.event.order.changed.remove_block', user=self.user, auth=self.auth, data={
'position': position.pk,
'positionid': position.positionid,
'position': op.position.pk,
'positionid': op.position.positionid,
'block_name': op.block_name,
})
if position.blocked and op.block_name in position.blocked:
position.blocked = [b for b in position.blocked if b != op.block_name]
if not position.blocked:
position.blocked = None
if op.position.blocked and op.block_name in op.position.blocked:
op.position.blocked = [b for b in op.position.blocked if b != op.block_name]
if not op.position.blocked:
op.position.blocked = None
if op.ignore_from_quota_while_blocked is not None:
position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
if not position.blocked:
op.position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
op.position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
if not op.position.blocked:
try:
bs = position.blocked_secrets.get(secret=position.secret)
bs = op.position.blocked_secrets.get(secret=op.position.secret)
bs.blocked = False
bs.save()
except BlockedTicketSecret.DoesNotExist:

View File

@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 18 14"
class="{{ cls }}">
<path d="M7.713 3.573c-.787-.124-1.677.472-1.511 1.529l.857 3.473c.116.579.578 1.086 1.317 1.086h3.166v3.504c0 1.108 1.556 1.113 1.556.019V8.682c0-.536-.376-1.116-1.099-1.116L9.52 7.563l-.752-2.936c-.147-.648-.583-.981-1.055-1.055v.001Z"></path>
<path d="M4.48 5.835a.6.6 0 0 0-.674.725l.71 3.441c.287 1.284 1.39 2.114 2.495 2.114h2.273c.807 0 .811-1.215-.01-1.215H7.188c-.753 0-1.375-.45-1.563-1.289l-.672-3.293c-.062-.3-.26-.452-.474-.483ZM7.433.102a1.468 1.468 0 1 0 0 2.937 1.469 1.469 0 1 0 0-2.937Z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 636 B

View File

@@ -40,7 +40,6 @@
<th class="iconcol"></th>
<th class="iconcol"></th>
<th class="iconcol"></th>
<th class="iconcol"></th>
<th class="text-right flip">{% trans "Default price" %}</th>
<th class="action-col-2"><span class="sr-only">Edit</span></th>
</tr>
@@ -112,14 +111,6 @@
<span class="fa fa-bars fa-fw text-muted" data-toggle="tooltip" title="{% trans "Product with variations" %}"></span>
{% endif %}
</td>
<td>
{% if i.requires_seat %}
<span data-toggle="tooltip"
title="{% if request.event.has_subevents %}{% trans "Product assigned to seating plan for one or more dates" context "subevent" %}{% else %}{% trans "Product assigned to seating plan" %}{% endif %}">
{% include "icons/seat.svg" with cls="svg-icon text-muted" %}
</span>
{% endif %}
</td>
<td>
{% if i.category.is_addon %}
<span class="fa fa-plus-square fa-fw text-muted" data-toggle="tooltip"

View File

@@ -413,7 +413,10 @@
{% endif %}
{% if line.seat %}
<br />
{% include "icons/seat.svg" with cls="svg-icon" %}
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668" class="svg-icon">
<path
d="m 1.9592032,1.8522629e-4 c -0.21468,0 -0.38861,0.17394000371 -0.38861,0.38861000371 0,0.21466 0.17393,0.38861 0.38861,0.38861 0.21468,0 0.3886001,-0.17395 0.3886001,-0.38861 0,-0.21467 -0.1739201,-0.38861000371 -0.3886001,-0.38861000371 z m 0.1049,0.84543000371 c -0.20823,-0.0326 -0.44367,0.12499 -0.39998,0.40462997 l 0.20361,1.01854 c 0.0306,0.15316 0.15301,0.28732 0.3483,0.28732 h 0.8376701 v 0.92708 c 0,0.29313 0.41187,0.29447 0.41187,0.005 v -1.19115 c 0,-0.14168 -0.0995,-0.29507 -0.29094,-0.29507 l -0.65578,-10e-4 -0.1757,-0.87644 C 2.3042533,0.95300523 2.1890432,0.86500523 2.0641032,0.84547523 Z m -0.58549,0.44906997 c -0.0946,-0.0134 -0.20202,0.0625 -0.17829,0.19172 l 0.18759,0.91054 c 0.0763,0.33956 0.36802,0.55914 0.66042,0.55914 h 0.6015201 c 0.21356,0 0.21448,-0.32143 -0.003,-0.32143 H 2.1954632 c -0.19911,0 -0.36364,-0.11898 -0.41341,-0.34107 l -0.17777,-0.87126 c -0.0165,-0.0794 -0.0688,-0.11963 -0.12557,-0.12764 z"/>
</svg>
{{ line.seat }}
{% endif %}
{% if line.voucher %}

View File

@@ -65,7 +65,7 @@ from pretix.api.serializers.item import (
from pretix.base.forms import I18nFormSet
from pretix.base.models import (
CartPosition, Item, ItemCategory, ItemVariation, Order, Question,
QuestionAnswer, QuestionOption, Quota, SeatCategoryMapping, Voucher,
QuestionAnswer, QuestionOption, Quota, Voucher,
)
from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
@@ -101,16 +101,10 @@ class ItemList(ListView):
template_name = 'pretixcontrol/items/index.html'
def get_queryset(self):
requires_seat = Exists(
SeatCategoryMapping.objects.filter(
product_id=OuterRef('pk'),
)
)
return Item.objects.filter(
event=self.request.event
).select_related("tax_rule").annotate(
var_count=Count('variations'),
requires_seat=requires_seat,
var_count=Count('variations')
).prefetch_related("category", "limit_sales_channels").order_by(
F('category__position').asc(nulls_first=True),
'category', 'position'

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 18 14">
<path d="M7.713 3.573c-.787-.124-1.677.472-1.511 1.529l.857 3.473c.116.579.578 1.086 1.317 1.086h3.166v3.504c0 1.108 1.556 1.113 1.556.019V8.682c0-.536-.376-1.116-1.099-1.116L9.52 7.563l-.752-2.936c-.147-.648-.583-.981-1.055-1.055v.001Z"></path>
<path d="M4.48 5.835a.6.6 0 0 0-.674.725l.71 3.441c.287 1.284 1.39 2.114 2.495 2.114h2.273c.807 0 .811-1.215-.01-1.215H7.188c-.753 0-1.375-.45-1.563-1.289l-.672-3.293c-.062-.3-.26-.452-.474-.483ZM7.433.102a1.468 1.468 0 1 0 0 2.937 1.469 1.469 0 1 0 0-2.937Z"></path>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668">
<path
d="m 1.9592032,1.8522629e-4 c -0.21468,0 -0.38861,0.17394000371 -0.38861,0.38861000371 0,0.21466 0.17393,0.38861 0.38861,0.38861 0.21468,0 0.3886001,-0.17395 0.3886001,-0.38861 0,-0.21467 -0.1739201,-0.38861000371 -0.3886001,-0.38861000371 z m 0.1049,0.84543000371 c -0.20823,-0.0326 -0.44367,0.12499 -0.39998,0.40462997 l 0.20361,1.01854 c 0.0306,0.15316 0.15301,0.28732 0.3483,0.28732 h 0.8376701 v 0.92708 c 0,0.29313 0.41187,0.29447 0.41187,0.005 v -1.19115 c 0,-0.14168 -0.0995,-0.29507 -0.29094,-0.29507 l -0.65578,-10e-4 -0.1757,-0.87644 C 2.3042533,0.95300523 2.1890432,0.86500523 2.0641032,0.84547523 Z m -0.58549,0.44906997 c -0.0946,-0.0134 -0.20202,0.0625 -0.17829,0.19172 l 0.18759,0.91054 c 0.0763,0.33956 0.36802,0.55914 0.66042,0.55914 h 0.6015201 c 0.21356,0 0.21448,-0.32143 -0.003,-0.32143 H 2.1954632 c -0.19911,0 -0.36364,-0.11898 -0.41341,-0.34107 l -0.17777,-0.87126 c -0.0165,-0.0794 -0.0688,-0.11963 -0.12557,-0.12764 z"/>
</svg>

Before

Width:  |  Height:  |  Size: 668 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-28 11:06+0000\n"
"PO-Revision-Date: 2025-04-29 18:00+0000\n"
"PO-Revision-Date: 2025-03-27 00:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix/"
"es/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.11.1\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -2996,9 +2996,11 @@ msgid "Repeat password"
msgstr "Repetir contraseña"
#: pretix/base/forms/questions.py:134 pretix/base/forms/questions.py:256
#, fuzzy
#| msgid "No country specified."
msgctxt "name_salutation"
msgid "not specified"
msgstr "sin especificar"
msgstr "No se especifica ningún país."
#: pretix/base/forms/questions.py:219
msgid "Please do not use special characters in names."
@@ -4268,14 +4270,20 @@ msgstr ""
"o acceder a una cuota agotada seguirá recibiendo el descuento."
#: pretix/base/models/discount.py:177
#, fuzzy
#| msgctxt "subevent"
#| msgid "All dates starting before"
msgctxt "subevent"
msgid "Available for dates starting from"
msgstr "Disponible para fechas a partir de"
msgstr "Todas las fechas empezando antes"
#: pretix/base/models/discount.py:182
#, fuzzy
#| msgctxt "subevent"
#| msgid "All dates starting before"
msgctxt "subevent"
msgid "Available for dates starting until"
msgstr "Disponible para fechas hasta el"
msgstr "Todas las fechas empezando antes"
#: pretix/base/models/discount.py:214
msgid ""
@@ -5591,12 +5599,19 @@ msgid "Unknown country code."
msgstr "Código de país desconocido."
#: pretix/base/models/items.py:1921 pretix/base/models/items.py:1923
#, fuzzy
#| msgid "The maximum count needs to be greater than the minimum count."
msgid "The maximum date must not be before the minimum value."
msgstr "La fecha máxima no debe ser anterior a la fecha mínima."
msgstr "El conteo máximo debe ser mayor que el conteo mínimo."
#: pretix/base/models/items.py:1925
#, fuzzy
#| msgid ""
#| "The maximum number of usages may not be lower than the minimum number of "
#| "usages."
msgid "The maximum value must not be lower than the minimum value."
msgstr "El valor máximo no debe ser inferior al mínimo."
msgstr ""
"El número máximo de usos no podrá ser inferior al número mínimo de usos."
#: pretix/base/models/items.py:1942
#: pretix/control/templates/pretixcontrol/items/question.html:90
@@ -11684,6 +11699,13 @@ msgid "Header image"
msgstr "Imagen de cabecera"
#: pretix/base/settings.py:2885
#, fuzzy
#| msgid ""
#| "If you provide a logo image, we will by default not show your event name "
#| "and date in the page header. By default, we show your logo with a size of "
#| "up to 1140x120 pixels. You can increase the size with the setting below. "
#| "We recommend not using small details on the picture as it will be resized "
#| "on smaller screens."
msgid ""
"If you provide a logo image, we will by default not show your event name and "
"date in the page header. If you use a white background, we show your logo "
@@ -11691,13 +11713,12 @@ msgid ""
"pixels. You can increase the size with the setting below. We recommend not "
"using small details on the picture as it will be resized on smaller screens."
msgstr ""
"Si proporciona una imagen de logotipo, por defecto no mostraremos el nombre "
"de su evento ni la fecha en la cabecera de la página. Si utiliza un fondo "
"blanco, mostraremos su logotipo con un tamaño máximo de 1140x120 píxeles. En "
"caso contrario, el tamaño máximo es de 1120x120 píxeles. Puede aumentar el "
"tamaño con la configuración que aparece a continuación. Recomendamos no "
"utilizar detalles pequeños en la imagen, ya que se redimensionará en las "
"pantallas más pequeñas."
"Si proporciona una imagen de logotipo, de forma predeterminada no "
"mostraremos el nombre ni la fecha de su evento en el encabezado de la "
"página. De forma predeterminada, mostramos su logotipo con un tamaño de "
"hasta 1140x120 píxeles. Puede aumentar el tamaño con la configuración "
"siguiente. Recomendamos no utilizar pequeños detalles en la imagen, ya que "
"cambiará de tamaño en pantallas más pequeñas."
#: pretix/base/settings.py:2906 pretix/base/settings.py:2949
msgid "Use header image in its full size"
@@ -11724,6 +11745,13 @@ msgstr ""
"título del evento."
#: pretix/base/settings.py:2929 pretix/control/forms/organizer.py:524
#, fuzzy
#| msgid ""
#| "If you provide a logo image, we will by default not show your "
#| "organization name in the page header. By default, we show your logo with "
#| "a size of up to 1140x120 pixels. You can increase the size with the "
#| "setting below. We recommend not using small details on the picture as it "
#| "will be resized on smaller screens."
msgid ""
"If you provide a logo image, we will by default not show your organization "
"name in the page header. If you use a white background, we show your logo "
@@ -11731,13 +11759,12 @@ msgid ""
"pixels. You can increase the size with the setting below. We recommend not "
"using small details on the picture as it will be resized on smaller screens."
msgstr ""
"Si proporciona una imagen de logotipo, por defecto no mostraremos el nombre "
"de su organización en la cabecera de la página. Si utiliza un fondo blanco, "
"mostraremos su logotipo con un tamaño máximo de 1140x120 píxeles. En caso "
"contrario, el tamaño máximo es de 1120x120 píxeles. Puede aumentar el tamaño "
"con la configuración que aparece a continuación. Recomendamos no utilizar "
"detalles pequeños en la imagen, ya que se redimensionará en las pantallas "
"más pequeñas."
"Si proporciona una imagen de logotipo, de forma predeterminada no "
"mostraremos el nombre de su organización en el encabezado de la página. De "
"forma predeterminada, mostramos su logotipo con un tamaño de hasta 1140x120 "
"píxeles. Puede aumentar el tamaño con la configuración siguiente. "
"Recomendamos no utilizar pequeños detalles en la imagen, ya que cambiará de "
"tamaño en pantallas más pequeñas."
#: pretix/base/settings.py:2959
msgid "Use header image also for events without an individually uploaded logo"
@@ -17904,8 +17931,8 @@ msgid_plural ""
"Are you sure you want to permanently delete the check-ins of "
"<strong>%(count)s tickets</strong>?"
msgstr[0] ""
"¿Está seguro de que desea eliminar permanentemente los registros de <strong"
">check-in</strong>?"
"¿Está seguro de que desea eliminar permanentemente los registros de "
"<strong>check-in</strong>?."
msgstr[1] ""
"¿Estás seguro de que deseas eliminar permanentemente los registros de "
"<strong>%(count)s check-in</strong>?"
@@ -24618,32 +24645,32 @@ msgstr "Idioma preferido"
#: pretix/control/templates/pretixcontrol/pdf/index.html:200
#: pretix/control/templates/pretixcontrol/pdf/index.html:210
#, fuzzy
#| msgid "Upload custom background"
msgid "Upload PDF as background"
msgstr "Subir PDF como fondo"
msgstr "Subir fondo personalizado"
#: pretix/control/templates/pretixcontrol/pdf/index.html:202
msgid ""
"You can upload a PDF to use as a custom background. The paper size will "
"match the PDF."
msgstr ""
"Puede cargar un PDF para utilizarlo como fondo personalizado. El tamaño del "
"papel coincidirá con el PDF."
#: pretix/control/templates/pretixcontrol/pdf/index.html:217
msgid "Download current background"
msgstr "Descargar fondo actual"
#: pretix/control/templates/pretixcontrol/pdf/index.html:224
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Or choose custom paper size"
msgstr "O elija un tamaño de papel personalizado"
msgstr "Fecha elegida por el cliente"
#: pretix/control/templates/pretixcontrol/pdf/index.html:226
msgid ""
"To manually change the paper size, you need to create a new, empty "
"background."
msgstr ""
"Para cambiar manualmente el tamaño del papel, debe crear un nuevo fondo "
"vacío."
#: pretix/control/templates/pretixcontrol/pdf/index.html:234
#: pretix/control/templates/pretixcontrol/pdf/index.html:321
@@ -28039,9 +28066,10 @@ msgid "until"
msgstr "hasta"
#: pretix/helpers/daterange.py:106
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid "{date_from} {date_to}"
msgid "{date_from}{until}{date_to}"
msgstr "{date_from}{until}{date_to}"
msgstr "{date_from} {date_to}"
#: pretix/helpers/images.py:61 pretix/helpers/images.py:67
#: pretix/helpers/images.py:85
@@ -31829,8 +31857,10 @@ msgid "Payer name"
msgstr "Nombre del pagador"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/control.html:91
#, fuzzy
#| msgid "Payment fee"
msgid "Payment receipt"
msgstr "Recibo de pago"
msgstr "Tarifa de pago"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/oauth_disconnect.html:12
msgid "Do you really want to disconnect your Stripe account?"

View File

@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-28 11:08+0000\n"
"PO-Revision-Date: 2025-04-29 18:00+0000\n"
"PO-Revision-Date: 2025-03-27 00: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"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
"js/es/>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.11.1\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -918,9 +918,12 @@ msgid "Open ticket shop"
msgstr "Abrir tienda de tickets"
#: pretix/static/pretixpresale/js/widget/widget.js:48
#, fuzzy
#| msgctxt "widget"
#| msgid "Resume checkout"
msgctxt "widget"
msgid "Checkout"
msgstr "Pasar por caja"
msgstr "Continuar pago"
#: pretix/static/pretixpresale/js/widget/widget.js:49
msgctxt "widget"
@@ -1078,31 +1081,31 @@ msgstr "Dom"
#: pretix/static/pretixpresale/js/widget/widget.js:81
msgid "Monday"
msgstr "Lunes"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:82
msgid "Tuesday"
msgstr "Martes"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:83
msgid "Wednesday"
msgstr "Miércoles"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:84
msgid "Thursday"
msgstr "Jueves"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:85
msgid "Friday"
msgstr "Viernes"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:86
msgid "Saturday"
msgstr "Sábado"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:87
msgid "Sunday"
msgstr "Domingo"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:90
msgid "January"

View File

@@ -4,8 +4,8 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-28 11:06+0000\n"
"PO-Revision-Date: 2025-04-29 18:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"PO-Revision-Date: 2025-04-03 20:00+0000\n"
"Last-Translator: Loïc Alejandro <loic.alejandro@e.email>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
">\n"
"Language: fr\n"
@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.11.1\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -3000,9 +3000,11 @@ msgid "Repeat password"
msgstr "Répéter le mot de passe"
#: pretix/base/forms/questions.py:134 pretix/base/forms/questions.py:256
#, fuzzy
#| msgid "No country specified."
msgctxt "name_salutation"
msgid "not specified"
msgstr "non spécifié"
msgstr "Aucun pays spécifié."
#: pretix/base/forms/questions.py:219
msgid "Please do not use special characters in names."
@@ -4283,14 +4285,20 @@ msgstr ""
"quota épuisé recevront toujours la réduction."
#: pretix/base/models/discount.py:177
#, fuzzy
#| msgctxt "subevent"
#| msgid "All dates starting before"
msgctxt "subevent"
msgid "Available for dates starting from"
msgstr "Disponible à partir de"
msgstr "Toutes les dates commençant avant"
#: pretix/base/models/discount.py:182
#, fuzzy
#| msgctxt "subevent"
#| msgid "All dates starting before"
msgctxt "subevent"
msgid "Available for dates starting until"
msgstr "Disponible pour des dates allant jusqu'au"
msgstr "Toutes les dates commençant avant"
#: pretix/base/models/discount.py:214
msgid ""
@@ -5621,12 +5629,20 @@ msgid "Unknown country code."
msgstr "Code de pays inconnu."
#: pretix/base/models/items.py:1921 pretix/base/models/items.py:1923
#, fuzzy
#| msgid "The maximum count needs to be greater than the minimum count."
msgid "The maximum date must not be before the minimum value."
msgstr "La date limite ne doit pas être antérieure à la date de début."
msgstr "Le nombre maximal doit être supérieur au nombre minimal."
#: pretix/base/models/items.py:1925
#, fuzzy
#| msgid ""
#| "The maximum number of usages may not be lower than the minimum number of "
#| "usages."
msgid "The maximum value must not be lower than the minimum value."
msgstr "La valeur maximale ne doit pas être inférieure à la valeur minimale."
msgstr ""
"Le nombre maximal dutilisations ne peut être inférieur au nombre minimal "
"dutilisations."
#: pretix/base/models/items.py:1942
#: pretix/control/templates/pretixcontrol/items/question.html:90
@@ -11805,6 +11821,13 @@ msgid "Header image"
msgstr "Image den-tête"
#: pretix/base/settings.py:2885
#, fuzzy
#| msgid ""
#| "If you provide a logo image, we will by default not show your event name "
#| "and date in the page header. By default, we show your logo with a size of "
#| "up to 1140x120 pixels. You can increase the size with the setting below. "
#| "We recommend not using small details on the picture as it will be resized "
#| "on smaller screens."
msgid ""
"If you provide a logo image, we will by default not show your event name and "
"date in the page header. If you use a white background, we show your logo "
@@ -11812,13 +11835,12 @@ msgid ""
"pixels. You can increase the size with the setting below. We recommend not "
"using small details on the picture as it will be resized on smaller screens."
msgstr ""
"Si vous fournissez une image de logo, nous n'afficherons pas, par défaut, le "
"nom et la date de votre événement dans l'en-tête de la page. Si vous "
"utilisez un fond blanc, nous affichons votre logo dans une taille maximale "
"de 1140x120 pixels. Sinon, la taille maximale est de 1120x120 pixels. Vous "
"pouvez augmenter la taille à l'aide du paramètre ci-dessous. Nous vous "
"recommandons de ne pas utiliser de petits détails sur l'image car elle sera "
"redimensionnée sur les petits écrans."
"Si vous fournissez une image de logo, nous nafficherons pas par défaut le "
"nom et la date de votre événement dans len-tête de la page. Par défaut, "
"nous affichons votre logo avec une taille allant jusquà 1140x120 pixels. "
"Vous pouvez augmenter la taille avec le paramètre ci-dessous. Nous vous "
"recommandons de ne pas utiliser de petits détails sur limage car elle sera "
"redimensionnée sur des écrans plus petits."
#: pretix/base/settings.py:2906 pretix/base/settings.py:2949
msgid "Use header image in its full size"
@@ -11847,6 +11869,13 @@ msgstr ""
"le titre de lévénement sera toujours affiché."
#: pretix/base/settings.py:2929 pretix/control/forms/organizer.py:524
#, fuzzy
#| msgid ""
#| "If you provide a logo image, we will by default not show your "
#| "organization name in the page header. By default, we show your logo with "
#| "a size of up to 1140x120 pixels. You can increase the size with the "
#| "setting below. We recommend not using small details on the picture as it "
#| "will be resized on smaller screens."
msgid ""
"If you provide a logo image, we will by default not show your organization "
"name in the page header. If you use a white background, we show your logo "
@@ -11854,13 +11883,12 @@ msgid ""
"pixels. You can increase the size with the setting below. We recommend not "
"using small details on the picture as it will be resized on smaller screens."
msgstr ""
"Si vous fournissez une image de logo, nous n'afficherons pas, par défaut, le "
"nom de votre organisation dans l'en-tête de la page. Si vous utilisez un "
"fond blanc, nous affichons votre logo dans une taille maximale de 1140x120 "
"pixels. Sinon, la taille maximale est de 1120x120 pixels. Vous pouvez "
"augmenter la taille à l'aide du paramètre ci-dessous. Nous vous recommandons "
"de ne pas utiliser de petits détails sur l'image car elle sera "
"redimensionnée sur les petits écrans."
"Si vous fournissez une image de logo, nous nafficherons pas par défaut le "
"nom de votre organisation dans len-tête de la page. Par défaut, nous "
"affichons votre logo avec une taille allant jusquà 1140x120 pixels. Vous "
"pouvez augmenter la taille avec le paramètre ci-dessous. Nous vous "
"recommandons de ne pas utiliser de petits détails sur limage car elle sera "
"redimensionnée sur des écrans plus petits."
#: pretix/base/settings.py:2959
msgid "Use header image also for events without an individually uploaded logo"
@@ -24805,32 +24833,32 @@ msgstr "Langue préférée"
#: pretix/control/templates/pretixcontrol/pdf/index.html:200
#: pretix/control/templates/pretixcontrol/pdf/index.html:210
#, fuzzy
#| msgid "Upload custom background"
msgid "Upload PDF as background"
msgstr "Télécharger un PDF comme arrière-pla"
msgstr "Télécharger un arrière-plan personnalisé"
#: pretix/control/templates/pretixcontrol/pdf/index.html:202
msgid ""
"You can upload a PDF to use as a custom background. The paper size will "
"match the PDF."
msgstr ""
"Vous pouvez télécharger un PDF à utiliser comme arrière-plan personnalisé. "
"La taille du papier correspondra à celle du PDF."
#: pretix/control/templates/pretixcontrol/pdf/index.html:217
msgid "Download current background"
msgstr "Télécharger l'arrière plan actuel"
#: pretix/control/templates/pretixcontrol/pdf/index.html:224
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Or choose custom paper size"
msgstr "Ou choisir un format de papier personnalisé"
msgstr "Date choisie par le client"
#: pretix/control/templates/pretixcontrol/pdf/index.html:226
msgid ""
"To manually change the paper size, you need to create a new, empty "
"background."
msgstr ""
"Pour modifier manuellement le format du papier, vous devez créer un nouvel "
"arrière-plan vide."
#: pretix/control/templates/pretixcontrol/pdf/index.html:234
#: pretix/control/templates/pretixcontrol/pdf/index.html:321
@@ -28260,9 +28288,10 @@ msgid "until"
msgstr "jusquà"
#: pretix/helpers/daterange.py:106
#, python-brace-format
#, fuzzy, python-brace-format
#| msgid "{date_from} {date_to}"
msgid "{date_from}{until}{date_to}"
msgstr "{date_from} {until}{date_to}"
msgstr "{date_from} {date_to}"
#: pretix/helpers/images.py:61 pretix/helpers/images.py:67
#: pretix/helpers/images.py:85
@@ -32086,8 +32115,10 @@ msgid "Payer name"
msgstr "Nom du payeur"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/control.html:91
#, fuzzy
#| msgid "Payment fee"
msgid "Payment receipt"
msgstr "Reçu de paiement"
msgstr "Frais de paiement"
#: pretix/plugins/stripe/templates/pretixplugins/stripe/oauth_disconnect.html:12
msgid "Do you really want to disconnect your Stripe account?"

View File

@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: French\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-28 11:08+0000\n"
"PO-Revision-Date: 2025-04-29 18:00+0000\n"
"PO-Revision-Date: 2025-03-27 00:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
"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.11.1\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -918,6 +918,9 @@ msgid "Open ticket shop"
msgstr "Ouvrir la billetterie"
#: pretix/static/pretixpresale/js/widget/widget.js:48
#, fuzzy
#| msgctxt "widget"
#| msgid "Resume checkout"
msgctxt "widget"
msgid "Checkout"
msgstr "Finaliser ma commande"
@@ -1077,31 +1080,31 @@ msgstr "Di"
#: pretix/static/pretixpresale/js/widget/widget.js:81
msgid "Monday"
msgstr "Lundi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:82
msgid "Tuesday"
msgstr "Mardi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:83
msgid "Wednesday"
msgstr "Mercredi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:84
msgid "Thursday"
msgstr "Jeudi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:85
msgid "Friday"
msgstr "Vendredi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:86
msgid "Saturday"
msgstr "Samedi"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:87
msgid "Sunday"
msgstr "Dimanche"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:90
msgid "January"

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-28 11:06+0000\n"
"PO-Revision-Date: 2025-04-29 01:00+0000\n"
"Last-Translator: Davide Manzella <manzella.davide97@gmail.com>\n"
"PO-Revision-Date: 2025-03-19 01:00+0000\n"
"Last-Translator: Rosariocastellana <rosariocastellana@gmail.com>\n"
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix/"
"it/>\n"
"Language: it\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.11.1\n"
"X-Generator: Weblate 5.10.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -27013,7 +27013,7 @@ msgstr ""
#: pretix/plugins/banktransfer/payment.py:161
msgid "Do not include hyphens in the payment reference."
msgstr "Non includere trattini nella referenza di pagamento."
msgstr ""
#: pretix/plugins/banktransfer/payment.py:162
msgid "This is required in some countries."
@@ -27025,7 +27025,7 @@ msgstr ""
#: pretix/plugins/banktransfer/payment.py:170
msgid "Prefix for the payment reference"
msgstr "Prefisso per il riferimento pagamento"
msgstr ""
#: pretix/plugins/banktransfer/payment.py:174
msgid "Additional text to show on pending orders"
@@ -27249,7 +27249,7 @@ msgstr "Ti daremo il codice di riferimento dopo aver completato l'ordine."
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:26
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html:39
msgid "Reference code (important):"
msgstr "Codice di riferimento personale (importante):"
msgstr ""
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_confirm.html:31
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:31
@@ -27288,7 +27288,7 @@ msgstr ""
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/control.html:38
msgid "Reference code"
msgstr "Codice di riferimento personale"
msgstr ""
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/import_assign.html:4
msgid ""
@@ -30057,7 +30057,7 @@ msgstr ""
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:19
msgid "Enter the entity number, reference number, and amount."
msgstr "Inserire il Numero dell'entità, il codice riferimento, e la quantità."
msgstr ""
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:25
msgid "Entity number:"

View File

@@ -1,7 +1,8 @@
.banktransfer-swiss-cross-overlay {
position: relative;
width: 150px;
margin: 0 auto;
height: 150px;
margin: 0 auto 10px;
}
.banktransfer-swiss-cross {
position: absolute;

View File

@@ -44,28 +44,34 @@
</p>
</div>
{% if settings.bank_details_type == "sepa" and any_barcodes %}
<div class="tabcontainer col-md-6 col-sm-6 hidden-xs text-center js-only blank-after">
<div id="banktransfer_qrcodes_tabs_content" class="tabpanels blank-after">
<div class="col-md-6 col-sm-6 hidden-xs text-center js-only blank-after">
<ul class="nav nav-tabs" id="banktransfer_qrcodes_tabs" role="tablist">
{% if swiss_qrbill %}
<div id="banktransfer_qrcodes_qrbill"
role="tabpanel"
tabindex="0"
aria-labelledby="banktransfer_qrcodes_qrbill_tab"
>
<div class="banktransfer-swiss-cross-overlay" role="figure" aria-labelledby="banktransfer_qrcodes_qrbill_tab banktransfer_qrcodes_label">
<li class="active"><a href="#banktransfer_qrcodes_qrbill" role="tab" id="banktransfer_qrcodes_qrbill_tab" data-toggle="tab" aria-controls="banktransfer_qrcodes_qrbill" aria-expanded="true">QR-bill</a></li>
{% endif %}
{% if eu_barcodes %}
<li {% if not swiss_qrbill %}class="active"{% endif %}><a href="#banktransfer_qrcodes_girocode" role="tab" id="banktransfer_qrcodes_girocode_tab" data-toggle="tab" aria-controls="banktransfer_qrcodes_girocode" aria-expanded="{% if swiss_qrbill %}false{% else %}true{% endif %}">EPC-QR</a></li>
<li class=""><a href="#banktransfer_qrcodes_bezahlcode" role="tab" id="banktransfer_qrcodes_bezahlcode_tab" data-toggle="tab" aria-controls="banktransfer_qrcodes_bezahlcode" aria-expanded="false">BezahlCode</a></li>
{% endif %}
</ul>
<div class="tab-content" id="banktransfer_qrcodes_tabs_content">
{% if swiss_qrbill %}
<div id="banktransfer_qrcodes_qrbill" class="tab-pane fade active in" role="tabpanel" aria-labelledby="banktransfer_qrcodes_qrbill_tab">
<p class="small">
{% trans "Scan the qr-code with your banking app" %}
</p>
<p class="banktransfer-swiss-cross-overlay">
<svg class="banktransfer-swiss-cross" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.8 19.8"><path stroke="#fff" stroke-width="1.436" d="M.7.7h18.4v18.4H.7z"/><path fill="#fff" d="M8.3 4h3.3v11H8.3z"/><path fill="#fff" d="M4.4 7.9h11v3.3h-11z"/></svg>
<script type="text/plain" data-size="150" data-replace-with-qr data-desc="{% trans 'Scan this image with your banking apps QR-Reader to start the payment process.' %}">{{swiss_qrbill}}</script>
</div>
</p>
</div>
{% endif %}
{% if eu_barcodes %}
<div id="banktransfer_qrcodes_girocode"
role="tabpanel"
tabindex="0"
{{ swiss_qrbill|yesno:'hidden,' }}
aria-labelledby="banktransfer_qrcodes_girocode_tab"
>
<div role="figure" aria-labelledby="banktransfer_qrcodes_girocode_tab banktransfer_qrcodes_label">
<div id="banktransfer_qrcodes_girocode" class="tab-pane fade {% if not swiss_qrbill %}active in{% endif %}" role="tabpanel" aria-labelledby="banktransfer_qrcodes_girocode_tab">
<p class="small">
{% trans "Scan the qr-code with your banking app" %}
</p>
<p>
<script type="text/plain" data-size="150" data-replace-with-qr data-desc="{% trans 'Scan this image with your banking apps QR-Reader to start the payment process.' %}">BCD
002
2
@@ -79,55 +85,20 @@ SCT
{{ code }}
</script>
</div>
</p>
</div>
<div id="banktransfer_qrcodes_bezahlcode"
role="tabpanel"
tabindex="0"
hidden
aria-labelledby="banktransfer_qrcodes_bezahlcode_tab"
>
<a aria-label="{% trans "Open BezahlCode in your banking app to start the payment process." %}" href="bank://singlepaymentsepa?name={{ settings.bank_details_sepa_name|urlencode }}&iban={{ settings.bank_details_sepa_iban }}&bic={{ settings.bank_details_sepa_bic }}&amount={{ amount|commadecimal }}&reason={{ code }}&currency={{ event.currency }}">
<div role="figure" aria-labelledby="banktransfer_qrcodes_bezahlcode_tab banktransfer_qrcodes_label">
<div id="banktransfer_qrcodes_bezahlcode" class="tab-pane fade" role="tabpanel" aria-labelledby="banktransfer_qrcodes_bezahlcode_tab">
<p class="small">
{% trans "Scan the qr-code with your banking app" %}
</p>
<p>
<a aria-label="{% trans "Open BezahlCode in your banking app to start the payment process." %}" href="bank://singlepaymentsepa?name={{ settings.bank_details_sepa_name|urlencode }}&iban={{ settings.bank_details_sepa_iban }}&bic={{ settings.bank_details_sepa_bic }}&amount={{ amount|commadecimal }}&reason={{ code }}&currency={{ event.currency }}">
<script type="text/plain" data-size="150" data-replace-with-qr data-desc="{% trans 'Scan this image with your banking apps QR-Reader to start the payment process.' %}">bank://singlepaymentsepa?name={{ settings.bank_details_sepa_name|urlencode }}&iban={{ settings.bank_details_sepa_iban }}&bic={{ settings.bank_details_sepa_bic }}&amount={{ amount|commadecimal }}&reason={{ code }}&currency={{ event.currency }}</script>
</div>
</a>
</a>
</p>
</div>
{% endif %}
</div>
<div id="banktransfer_qrcodes_tabs" role="tablist" aria-labelledby="banktransfer_qrcodes_label" class="blank-after btn-group">
{% if swiss_qrbill %}
<button
class="btn btn-default"
id="banktransfer_qrcodes_qrbill_tab"
type="button"
role="tab"
aria-controls="banktransfer_qrcodes_qrbill"
aria-selected="true"
tabindex="-1">QR-bill</button>
{% endif %}
{% if eu_barcodes %}
<button
class="btn btn-default"
id="banktransfer_qrcodes_girocode_tab"
type="button"
role="tab"
aria-controls="banktransfer_qrcodes_girocode"
aria-selected="{{ swiss_qrbill|yesno:"false,true" }}"
tabindex="-1">EPC-QR</button>
<button
class="btn btn-default"
id="banktransfer_qrcodes_bezahlcode_tab"
type="button"
role="tab"
aria-controls="banktransfer_qrcodes_bezahlcode"
aria-selected="false"
tabindex="-1">BezahlCode</button>
{% endif %}
</div>
<p class="text-muted" id="banktransfer_qrcodes_label">
{% trans "Scan the QR code with your banking app" %}
</p>
</div>
{% endif %}
</div>
@@ -171,4 +142,4 @@ SCT
</div>
</form>
<hr>
{% endif %}
{% endif %}

View File

@@ -33,7 +33,6 @@ def render_label(content, label_for=None, label_class=None, label_title='', labe
"""
Render a label with content
"""
tag = 'label'
attrs = attrs or {}
if label_for:
attrs['for'] = label_for
@@ -59,16 +58,15 @@ def render_label(content, label_for=None, label_class=None, label_title='', labe
attrs['class'] += ' label-empty'
# usually checkboxes have overall empty labels and special labels per checkbox
# => remove for-attribute as well as "required"-text appended to label
tag = 'div'
if 'for' in attrs:
del attrs['for']
elif not optional:
opt += '<i class="label-required">{}</i>'.format(pgettext('form', 'required'))
opt += '<i class="sr-only label-required">, {}</i>'.format(pgettext('form', 'required'))
builder = '<{tag}{attrs}>{content}{opt}</{tag}>'
return format_html(
builder,
tag=tag,
tag='label',
attrs=mark_safe(flatatt(attrs)) if attrs else '',
opt=mark_safe(opt),
content=text_value(content),

View File

@@ -23,7 +23,10 @@
{% trans "Seat" %}
</label>
<div class="col-md-9 form-control-text">
{% include "icons/seat.svg" with cls="svg-icon" %}
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668" class="svg-icon">
<path
d="m 1.9592032,1.8522629e-4 c -0.21468,0 -0.38861,0.17394000371 -0.38861,0.38861000371 0,0.21466 0.17393,0.38861 0.38861,0.38861 0.21468,0 0.3886001,-0.17395 0.3886001,-0.38861 0,-0.21467 -0.1739201,-0.38861000371 -0.3886001,-0.38861000371 z m 0.1049,0.84543000371 c -0.20823,-0.0326 -0.44367,0.12499 -0.39998,0.40462997 l 0.20361,1.01854 c 0.0306,0.15316 0.15301,0.28732 0.3483,0.28732 h 0.8376701 v 0.92708 c 0,0.29313 0.41187,0.29447 0.41187,0.005 v -1.19115 c 0,-0.14168 -0.0995,-0.29507 -0.29094,-0.29507 l -0.65578,-10e-4 -0.1757,-0.87644 C 2.3042533,0.95300523 2.1890432,0.86500523 2.0641032,0.84547523 Z m -0.58549,0.44906997 c -0.0946,-0.0134 -0.20202,0.0625 -0.17829,0.19172 l 0.18759,0.91054 c 0.0763,0.33956 0.36802,0.55914 0.66042,0.55914 h 0.6015201 c 0.21356,0 0.21448,-0.32143 -0.003,-0.32143 H 2.1954632 c -0.19911,0 -0.36364,-0.11898 -0.41341,-0.34107 l -0.17777,-0.87126 c -0.0165,-0.0794 -0.0688,-0.11963 -0.12557,-0.12764 z"/>
</svg>
{{ form.position.seat }}
</div>
</div>

View File

@@ -100,7 +100,10 @@
{% trans "Seat" %}
</label>
<div class="col-md-9 form-control-text">
{% include "icons/seat.svg" with cls="svg-icon" %}
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668" class="svg-icon">
<path
d="m 1.9592032,1.8522629e-4 c -0.21468,0 -0.38861,0.17394000371 -0.38861,0.38861000371 0,0.21466 0.17393,0.38861 0.38861,0.38861 0.21468,0 0.3886001,-0.17395 0.3886001,-0.38861 0,-0.21467 -0.1739201,-0.38861000371 -0.3886001,-0.38861000371 z m 0.1049,0.84543000371 c -0.20823,-0.0326 -0.44367,0.12499 -0.39998,0.40462997 l 0.20361,1.01854 c 0.0306,0.15316 0.15301,0.28732 0.3483,0.28732 h 0.8376701 v 0.92708 c 0,0.29313 0.41187,0.29447 0.41187,0.005 v -1.19115 c 0,-0.14168 -0.0995,-0.29507 -0.29094,-0.29507 l -0.65578,-10e-4 -0.1757,-0.87644 C 2.3042533,0.95300523 2.1890432,0.86500523 2.0641032,0.84547523 Z m -0.58549,0.44906997 c -0.0946,-0.0134 -0.20202,0.0625 -0.17829,0.19172 l 0.18759,0.91054 c 0.0763,0.33956 0.36802,0.55914 0.66042,0.55914 h 0.6015201 c 0.21356,0 0.21448,-0.32143 -0.003,-0.32143 H 2.1954632 c -0.19911,0 -0.36364,-0.11898 -0.41341,-0.34107 l -0.17777,-0.87126 c -0.0165,-0.0794 -0.0688,-0.11963 -0.12557,-0.12764 z"/>
</svg>
{{ pos.seat }}
</div>
</div>

View File

@@ -205,7 +205,7 @@
{% else %}
<fieldset class="input-item-count-group" aria-describedby="c-{{ form.pos.pk }}-{{ category_idx }}-addon-count-desc cp-{{ form.pos.pk }}-item-{{ item.pk }}-min-order">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }}, {{ var }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}, {{ var }}: {% trans "Decrease quantity" %}">-</button>
<button type="button" data-step="-1" data-controls="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}">-</button>
<input type="number" class="form-control input-item-count" placeholder="0" min="0"
{% if var.initial %}value="{{ var.initial }}"{% endif %}
{% if item.free_price %}
@@ -215,7 +215,7 @@
id="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}"
name="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}"
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}, {{ var }}: {% trans "Increase quantity" %}">+</button>
<button type="button" data-step="1" data-controls="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}">+</button>
</fieldset>
{% endif %}
</div>
@@ -351,7 +351,7 @@
{% else %}
<fieldset class="input-item-count-group" aria-describedby="c-{{ form.pos.pk }}-{{ category_idx }}-addon-count-desc cp-{{ form.pos.pk }}-item-{{ item.pk }}-min-order">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="cp_{{ form.pos.pk }}_item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}: {% trans "Decrease quantity" %}">-</button>
<button type="button" data-step="-1" data-controls="cp_{{ form.pos.pk }}_item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}">-</button>
<input type="number" class="form-control input-item-count" placeholder="0" min="0"
{% if item.free_price %}
data-checked-onchange="price-item-{{ form.pos.pk }}-{{ item.pk }}"
@@ -361,7 +361,7 @@
name="cp_{{ form.pos.pk }}_item_{{ item.id }}"
id="cp_{{ form.pos.pk }}_item_{{ item.id }}"
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="cp_{{ form.pos.pk }}_item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}: {% trans "Increase quantity" %}">+</button>
<button type="button" data-step="1" data-controls="cp_{{ form.pos.pk }}_item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}">+</button>
</fieldset>
{% endif %}
</div>

View File

@@ -11,11 +11,8 @@
<span role="columnheader" aria-sort="none">{% trans "Product" %}</span>
{% if download %}
<span role="columnheader" aria-sort="none">{% trans "Ticket download" %}</span>
{% else %}
<span role="columnheader" aria-sort="none">{% trans "Quantity" %}</span>
{% if not hide_prices %}
<span role="columnheader" aria-sort="none">{% trans "Price per item" %}</span>
{% endif %}
{% elif not hide_prices %}
<span role="columnheader" aria-sort="none">{% trans "Price per item" %}</span>
{% endif %}
{% if not hide_prices %}
<span role="columnheader" aria-sort="none">{% trans "Price total" %}</span>
@@ -44,8 +41,11 @@
<div class="cart-icon-details">
<dt class="sr-only">{% trans "Seat:" %}</dt>
<dd>
{% include "icons/seat.svg" with cls="svg-icon" %}
{{ line.seat }}
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668" class="svg-icon">
<path
d="m 1.9592032,1.8522629e-4 c -0.21468,0 -0.38861,0.17394000371 -0.38861,0.38861000371 0,0.21466 0.17393,0.38861 0.38861,0.38861 0.21468,0 0.3886001,-0.17395 0.3886001,-0.38861 0,-0.21467 -0.1739201,-0.38861000371 -0.3886001,-0.38861000371 z m 0.1049,0.84543000371 c -0.20823,-0.0326 -0.44367,0.12499 -0.39998,0.40462997 l 0.20361,1.01854 c 0.0306,0.15316 0.15301,0.28732 0.3483,0.28732 h 0.8376701 v 0.92708 c 0,0.29313 0.41187,0.29447 0.41187,0.005 v -1.19115 c 0,-0.14168 -0.0995,-0.29507 -0.29094,-0.29507 l -0.65578,-10e-4 -0.1757,-0.87644 C 2.3042533,0.95300523 2.1890432,0.86500523 2.0641032,0.84547523 Z m -0.58549,0.44906997 c -0.0946,-0.0134 -0.20202,0.0625 -0.17829,0.19172 l 0.18759,0.91054 c 0.0763,0.33956 0.36802,0.55914 0.66042,0.55914 h 0.6015201 c 0.21356,0 0.21448,-0.32143 -0.003,-0.32143 H 2.1954632 c -0.19911,0 -0.36364,-0.11898 -0.41341,-0.34107 l -0.17777,-0.87126 c -0.0165,-0.0794 -0.0688,-0.11963 -0.12557,-0.12764 z"/>
</svg>
{{ line.seat }}
</dd>
</div>
{% endif %}
@@ -392,20 +392,12 @@
{% endfor %}
{% endfor %}
{% for fee in cart.fees %}
<div role="row" class="row cart-row">
<div role="cell" class="col-md-4 col-xs-6">
<div class="row cart-row">
<div class="col-md-4 col-xs-6">
<strong>{{ fee.get_fee_type_display }}</strong>
</div>
{% if download %}
<div role="cell"></div>
{% else %}
<div role="cell"></div>
{% if not hide_prices %}
<div role="cell"></div>
{% endif %}
{% endif %}
{% if not hide_prices %}
<div role="cell" class="col-md-3 col-xs-6 col-md-offset-5 price">
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
{% if event.settings.display_net_prices %}
<strong>{{ fee.net_value|money:event.currency }}</strong>
{% if fee.tax_rate %}

View File

@@ -221,7 +221,7 @@
{% else %}
<fieldset class="input-item-count-group">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }}, {{ var }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}, {{ var }}: {% trans "Decrease quantity" %}"
<button type="button" data-step="-1" data-controls="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}"
{% if not ev.presale_is_running %}disabled{% endif %}>-</button>
<input type="number" class="form-control input-item-count" placeholder="0" min="0"
{% if not ev.presale_is_running %}disabled{% endif %}
@@ -232,7 +232,7 @@
id="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}"
name="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}"
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}, {{ var }}: {% trans "Increase quantity" %}"
<button type="button" data-step="1" data-controls="{{ form_prefix }}variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}"
{% if not ev.presale_is_running %}disabled{% endif %}>+</button>
</fieldset>
{% endif %}
@@ -262,7 +262,7 @@
</a>
{% endif %}
<div class="product-description {% if item.picture %}with-picture{% endif %}">
<h{{ headline_level|default:3|add:1 }} class="h4" id="{{ form_prefix }}item-{{ item.pk }}-legend">{{ item.name }}</h{{ headline_level|default:3|add:1 }}>
<h{{ headline_level|default:3|add:1 }} class="h4" id="{{ form_prefix }}item-{{ item.pk }}-legend">{{ item.name }}</h{{ headline_level|default:3 }}>
{% if item.description %}
<div id="{{ form_prefix }}item-{{ item.pk }}-description" class="product-description">
{{ item.description|localize|rich_text }}
@@ -373,7 +373,7 @@
{% else %}
<fieldset class="input-item-count-group">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="{{ form_prefix }}item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}: {% trans "Decrease quantity" %}"
<button type="button" data-step="-1" data-controls="{{ form_prefix }}item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}"
{% if not ev.presale_is_running %}disabled{% endif %}>-</button>
<input type="number" class="form-control input-item-count" placeholder="0" min="0"
{% if not ev.presale_is_running %}disabled{% endif %}
@@ -385,7 +385,7 @@
name="{{ form_prefix }}item_{{ item.id }}"
id="{{ form_prefix }}item_{{ item.id }}"
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="{{ form_prefix }}item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}: {% trans "Increase quantity" %}"
<button type="button" data-step="1" data-controls="{{ form_prefix }}item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}"
{% if not ev.presale_is_running %}disabled{% endif %}>+</button>
</fieldset>
{% endif %}

View File

@@ -16,7 +16,6 @@
<br>
<span data-time="{{ subev.date_from.isoformat }}" data-timezone="{{ event.timezone }}" data-time-short>
{% icon "clock-o" %}
<span class="sr-only">{% trans "Time of day" %}</span>
<time datetime="{{ subev.date_from.isoformat }}">{{ subev.date_from|date:"TIME_FORMAT" }}</time>
</span>
{% endif %}

View File

@@ -233,14 +233,14 @@
{% else %}
<fieldset class="input-item-count-group">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }}, {{ var }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}, {{ var }}: {% trans "Decrease quantity" %}">-</button>
<button type="button" data-step="-1" data-controls="variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}">-</button>
<input type="number" class="form-control input-item-count" placeholder="0" min="0"
max="{{ var.order_max }}"
id="variation_{{ item.id }}_{{ var.id }}"
name="variation_{{ item.id }}_{{ var.id }}"
{% if options == 1 %}value="1"{% endif %}
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}, {{ var }}: {% trans "Increase quantity" %}">+</button>
<button type="button" data-step="1" data-controls="variation_{{ item.id }}_{{ var.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}">+</button>
</fieldset>
{% endif %}
{% else %}
@@ -388,7 +388,7 @@
{% else %}
<fieldset class="input-item-count-group">
<legend class="sr-only">{% blocktrans with item=item.name %}Add {{ item }} to cart{% endblocktrans %}</legend>
<button type="button" data-step="-1" data-controls="item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="- {{ item }}: {% trans "Decrease quantity" %}">-</button>
<button type="button" data-step="-1" data-controls="item_{{ item.id }}" class="btn btn-default input-item-count-dec" aria-label="{% trans "Decrease quantity" %}">-</button>
<input type="number" class="form-control input-item-count"
placeholder="0" min="0"
max="{{ item.order_max }}"
@@ -396,7 +396,7 @@
name="item_{{ item.id }}"
{% if options == 1 %}value="1"{% endif %}
aria-label="{% trans "Quantity" %}">
<button type="button" data-step="1" data-controls="item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="+ {{ item }}: {% trans "Increase quantity" %}">+</button>
<button type="button" data-step="1" data-controls="item_{{ item.id }}" class="btn btn-default input-item-count-inc" aria-label="{% trans "Increase quantity" %}">+</button>
</fieldset>
{% endif %}
{% else %}

View File

@@ -69,7 +69,6 @@
<br>
<span class="text-muted" data-time="{{ e.date_from.isoformat }}" data-timezone="{{ e.tzname }}">
{% icon "clock-o" %}
<span class="sr-only">{% trans "Time of day" %}</span>
<time datetime="{{ e.date_from|date_fast:"H:i" }}">{{ e.date_from|date:"TIME_FORMAT" }}</time>
{% if e.settings.show_date_to and e.date_to and e.date_to.date == e.date_from.date %}
<span aria-hidden="true"></span><span class="sr-only">{% trans "until" context "timerange" %}</span>

View File

@@ -928,9 +928,7 @@ class DayCalendarView(OrganizerViewMixin, EventListMixin, TemplateView):
def _set_date(self):
if 'date' in self.request.GET:
self.tz = self.request.organizer.timezone
self.date = (
parse_date_localized(self.request.GET.get('date')) or now().astimezone(self.tz)
).date()
self.date = parse_date_localized(self.request.GET.get('date')).date() or now().astimezone(self.tz).date()
else:
self._set_date_to_next_event()

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,8 @@
"private": true,
"scripts": {},
"dependencies": {
"@babel/core": "^7.27.1",
"@babel/preset-env": "^7.27.1",
"@babel/core": "^7.26.10",
"@babel/preset-env": "^7.26.9",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^16.0.1",
"vue": "^2.7.16",

View File

@@ -227,10 +227,6 @@ svg.svg-icon {
top: 2px;
}
.text-muted path {
fill: $text-muted;
}
.link-muted a, a.link-muted {
color: $text-muted;
}

View File

@@ -4,26 +4,6 @@ $(document).on("pretix:bind-forms", function () {
function cleanup(l) {
return $.trim(l.replace(/\n/g, ", "));
}
function combine($sel) {
var parts = [
$sel.filter("[name*=street]").val(),
$sel.filter("[name*=zipcode]").val(),
$sel.filter("[name*=city]").val(),
$sel.filter("[name*=state]").val(),
$sel.filter("[name*=country]").find("option:selected").text(),
$sel.filter("[name*=location]").val(),
]
var res = "";
for (var val of parts) {
if (val) {
if (res) {
res += ", "
}
res += val
}
}
return cleanup(res)
}
$(".geodata-section").each(function () {
// Geocoding
// detach notifications and append them to first label (should be from location)
@@ -33,26 +13,8 @@ $(document).on("pretix:bind-forms", function () {
var lat;
var lon;
var $updateButton = $("[data-action=update]", this);
var $location;
// The .geodata-section is expected to include either...
// ... an English "location" field
if ($("textarea[lang=en], input[lang=en]", this).length) {
$location = $("textarea[lang=en], input[lang=en], select", this).not("[name*=geo_]");
}
// ... a "location" field in any other language
if (!$location || !$location.length) {
var lang = $("textarea, input[type=text]", this).not("[name*=geo_]").first().attr("lang");
if (lang) {
$location = $("textarea[lang=" + lang + "], input[lang=" + lang + "], select", this);
}
}
// ... or a set of fields like a full address form
if (!$location || !$location.length) {
$location = $("textarea, input, select", this).not("[name*=geo_]");
}
var $location = $("textarea[lang=en], input[lang=en]", this).first();
if (!$location.length) $location = $("textarea, input[type=text]", this).first();
if (!$lat.length || !$lon.length || !$location.length) {
return;
@@ -61,7 +23,7 @@ $(document).on("pretix:bind-forms", function () {
var debounceLoad, debounceLatLonChange, delayUpdateDismissal;
var touched = $lat.val() !== "";
var xhr;
var lastLocation = combine($location);
var lastLocation = cleanup($location.val());
function load() {
window.clearTimeout(debounceLoad);
@@ -70,7 +32,7 @@ $(document).on("pretix:bind-forms", function () {
xhr = null;
}
var q = combine($location);
var q = cleanup($location.val());
if (q === "" || q === lastLocation) return;
lastLocation = q;

View File

@@ -60,7 +60,6 @@ var form_handlers = function (el) {
locale: $("body").attr("data-datetimelocale"),
useCurrent: false,
showClear: !$(this).prop("required"),
keepInvalid: true,
icons: {
time: 'fa fa-clock-o',
date: 'fa fa-calendar',
@@ -315,49 +314,6 @@ function setup_basics(el) {
$(this).parent().parent().find('.addon-variation-description').stop().slideDown();
}
});
// tabs - see https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-automatic/ for reference
el.find('.tabcontainer').each(function() {
var currentTab;
function setCurrentTab(tab) {
if (tab == currentTab) return;
if (currentTab) {
currentTab.setAttribute('aria-selected', 'false');
currentTab.tabIndex = -1;
currentTab.classList.remove('active');
document.getElementById(currentTab.getAttribute('aria-controls')).setAttribute('hidden', 'hidden');
}
tab.setAttribute('aria-selected', 'true');
tab.removeAttribute('tabindex');
tab.classList.add('active');
document.getElementById(tab.getAttribute('aria-controls')).removeAttribute('hidden');
currentTab = tab;
}
var tabs = $('button[role=tab]').on('keydown', function(event) {
if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].indexOf(event.key) == -1) {
return;
}
event.stopPropagation();
event.preventDefault();
if (event.key == 'ArrowLeft') {
setCurrentTab(currentTab.previousElementSibling || lastTab);
} else if (event.key == 'ArrowRight') {
setCurrentTab(currentTab.nextElementSibling || firstTab);
} else if (event.key == 'Home') {
setCurrentTab(firstTab);
} else if (event.key == 'End') {
setCurrentTab(lastTab);
}
currentTab.focus();
}).on('click', function (event) {
setCurrentTab(this);
});
var firstTab = tabs.first().get(0);
var lastTab = tabs.last().get(0);
setCurrentTab(tabs.filter('[aria-selected=true]').get(0));
});
}
function setup_week_calendar() {

View File

@@ -145,23 +145,10 @@ output {
color: $brand-primary;
font-weight: bold;
}
.label-required {
color: $text-muted;
display: block;
font-weight: normal;
font-style: normal;
font-size: 85%;
.form-group.required .control-label:after {
content: '*';
color: $brand-primary;
}
.checkbox .label-required {
display: inline;
&:before {
content: " (";
}
&:after {
content: ")";
}
}
.form-control-text {
padding-top: 7px;
}

View File

@@ -112,10 +112,9 @@ a, .btn-link {
*/
/* bootstrap sets outline-offset with :active:focus so we need to match specifity of selector */
/* see line 26, pretix/static/bootstrap/scss/bootstrap/_buttons.scss */
button:focus, a:focus, .btn:focus, summary:focus, div:focus,
button:focus, a:focus, .btn:focus, summary:focus,
/*button:active, a:active, .btn:active, summary:active,*/
button:active:focus, a:active:focus, .btn:active:focus, summary:active:focus, div:active:focus,
button.active:focus, a.active:focus, .btn.active:focus,
button:active:focus, a:active:focus, .btn:active:focus, summary:active:focus,
input:focus, .form-control:focus, .btn-checkbox:has(input:focus),
.input-item-count-group:has(input:focus), .input-group-price:has(input:focus) {
outline: 2px solid $link-hover-color;

View File

@@ -1734,29 +1734,6 @@ class OrderChangeManagerTests(TestCase):
with self.assertRaises(OrderError):
self.ocm.change_price(self.op1, 25)
@classscope(attr='o')
def test_cancel_and_change_addon(self):
se1 = self.event.subevents.create(name="Foo", date_from=now())
se2 = self.event.subevents.create(name="Bar", date_from=now())
self.op1.subevent = se1
self.op1.save()
self.op2.subevent = se1
self.op2.save()
self.quota.subevent = se2
self.quota.save()
op3 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None, addon_to=self.op1,
price=Decimal("0.00"), positionid=3, subevent=se1,
)
self.ocm.cancel(self.op1)
self.ocm.change_subevent(op3, se2)
self.ocm.commit()
# Expected: the addon is also canceled
# Bug we had: the addon is not canceled
op3.refresh_from_db()
assert op3.canceled
@classscope(attr='o')
def test_cancel_all_in_order(self):
self.ocm.cancel(self.op1)