Compare commits

...

27 Commits

Author SHA1 Message Date
Raphael Michel
d304d394b3 Update src/pretix/static/pretixbase/scss/_theme.scss
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2025-05-06 11:14:22 +02:00
Raphael Michel
075b13951a Use updated seat icon 2025-05-05 12:45:53 +02:00
Raphael Michel
ef386eb358 Product list: Show icon for seated products 2025-04-17 16:47:01 +02:00
luelista
d8ec489b13 OrderChangeManager: Fix for change_tax_rule and recalculate_taxes in same transaction (Z#23187299) (#4964)
* Add test case

* Do not overwrite tax_rule in PriceOperation
2025-03-31 12:27:45 +02:00
Raphael Michel
804b048dbb Check-in API: Return order locale, and allow to use order locale for … (#4969)
* Check-in API: Return order locale, and allow to use order locale for reasons

* Fix failing tests
2025-03-31 12:26:46 +02:00
Renne Rocha
a3d721c08b Add Federal district (DF) to state dropdown for Brazil (BR) (#4966) 2025-03-31 12:15:17 +02:00
dependabot[bot]
b5544b120d Update djangorestframework requirement from ==3.15.* to ==3.16.* (#4965)
Updates the requirements on [djangorestframework](https://github.com/encode/django-rest-framework) to permit the latest version.
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.15.0...3.16.0)

---
updated-dependencies:
- dependency-name: djangorestframework
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 12:14:53 +02:00
Raphael Michel
5138e86cf1 Order search: Keep searching in canceled positions (Z#23187097) (#4963) 2025-03-31 12:14:00 +02:00
luelista
f455152447 Show link to stripe payment receipt in backend (Z#23187178) (#4961)
* Show link to stripe payment receipt in backend (Z#23187178)

* Revert "Show link to stripe payment receipt in backend (Z#23187178)"

This reverts commit 4a261ac1ac.

* Show link to stripe payment receipt in backend payment details (Z#23187178)
2025-03-31 12:13:04 +02:00
Richard Schreiber
9447e5802d PDF-Editor: improve UI for page-size and background PDF (#4959)
* PDF-Editor: improve UI for page-size and background PDF

* Update src/pretix/control/templates/pretixcontrol/pdf/index.html

Co-authored-by: leiascyr <156191181+leiascyr@users.noreply.github.com>

* Update src/pretix/control/templates/pretixcontrol/pdf/index.html

Co-authored-by: leiascyr <156191181+leiascyr@users.noreply.github.com>

* Update label text

Co-authored-by: Raphael Michel <michel@rami.io>

---------

Co-authored-by: Raphael Michel <michel@rami.io>
Co-authored-by: leiascyr <156191181+leiascyr@users.noreply.github.com>
2025-03-31 12:11:49 +02:00
Jan Van Haver
e5fc7144e4 Translations: Update Dutch
Currently translated at 77.5% (183 of 236 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/nl/

powered by weblate
2025-03-31 12:09:05 +02:00
Jan Van Haver
a7c8bb0f02 Translations: Update Dutch
Currently translated at 99.8% (5853 of 5863 strings)

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

powered by weblate
2025-03-31 12:09:05 +02:00
Jan Van Haver
fbb6246020 Translations: Update Dutch
Currently translated at 99.5% (5836 of 5863 strings)

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

powered by weblate
2025-03-31 12:09:05 +02:00
luelista
d39a01af4d Fix bulk edit of revoked devices (Z#23187227) (#4960)
When selecting revoked devices and using bulk edit on them, the edit was performed 
either *on all active devices* or not at all. This commit fixes that behaviour so that the 
selected devices are edited.
2025-03-28 17:59:55 +01:00
Raphael Michel
d928adf7a3 Sort organizers in typeahead by number of events (Z##23185900) (#4912) 2025-03-27 17:28:10 +01:00
luelista
4755200ab0 order_overview: allow filtering by time (#4958) 2025-03-27 17:23:08 +01:00
Phin Wolkwitz
0b8a7349c7 Discounts: Add applicability date ranges (Z#23151897) (#4927)
* Add event date fields, add preliminary range check

* Remove function, use filtered queryset for subevent id limit

* Improve and fix date range check

* Add formfields

* Add tests

* Improve tests

* Add new fields to API and documentation

* Add migration

* Change description according to suggestion

* Change discount apply signature, remove unnecessary query

* Rename new fields, simplify range check

* Rename fields in template

* Apply suggestions from code review

Co-authored-by: Raphael Michel <michel@rami.io>

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2025-03-27 15:36:20 +01:00
Richard Schreiber
1a1948e3fa [A11y] Improve HTML-output for date-ranges 2025-03-27 13:21:25 +01:00
Richard Schreiber
f70874b21c [A11y] Widget: add missing labels to dialog and iframe 2025-03-27 13:20:13 +01:00
Richard Schreiber
1c8bcca846 [A11y] Improve focus management for widget overlay 2025-03-27 13:18:59 +01:00
Raphael Michel
6c7041c875 Add a label for empty salutation option (Z#23183319) (#4913) 2025-03-27 12:09:04 +01:00
CVZ-es
8c9a94f87e Translations: Update Spanish
Currently translated at 100.0% (236 of 236 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2025-03-27 11:05:45 +01:00
CVZ-es
6f3c2ed444 Translations: Update Spanish
Currently translated at 100.0% (5863 of 5863 strings)

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

powered by weblate
2025-03-27 11:05:45 +01:00
CVZ-es
736792fc01 Translations: Update French
Currently translated at 100.0% (236 of 236 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/fr/

powered by weblate
2025-03-27 11:05:45 +01:00
CVZ-es
bacb40fd7f Translations: Update French
Currently translated at 100.0% (5863 of 5863 strings)

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

powered by weblate
2025-03-27 11:05:45 +01:00
Raphael Michel
42399c3488 Date picker: Guess default time 23:59 for end dates (Z#23182900) (#4917)
* Date picker: Guess default time 23:59 for end dates (Z#23182900)

* Update src/pretix/static/pretixcontrol/js/ui/main.js

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

* Update src/pretix/static/pretixpresale/js/ui/main.js

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

---------

Co-authored-by: luelista <weller@rami.io>
2025-03-27 11:04:02 +01:00
Raphael Michel
592b98b83a Bump version to 2025.4.0.dev0 2025-03-26 16:08:03 +01:00
54 changed files with 932 additions and 760 deletions

View File

@@ -54,6 +54,11 @@ Checking a ticket in
this request twice with the same nonce, the second request will also succeed but will always
create only one check-in object even when the previous request was successful as well. This
allows for a certain level of idempotency and enables you to re-try after a connection failure.
:<json boolean use_order_locale: Specifies that pretix should use the customer's language (``locale`` field from the
order) when building texts (currently only the ``reason_explanation`` response field).
Defaults to ``false`` in which case the server will determine the language (currently
the event default language, might change in the future with support for the
``Accept-Language`` header).
:>json string status: ``"ok"``, ``"incomplete"``, or ``"error"``
:>json string reason: Reason code, only set on status ``"error"``, see below for possible values.
:>json string reason_explanation: Human-readable explanation, only set on status ``"error"`` and reason ``"rules"``, can be null.
@@ -62,7 +67,9 @@ Checking a ticket in
will only include check-ins for the selected list. (2) An additional boolean property
``require_attention`` will inform you whether either the order or the item have the
``checkin_attention`` flag set. (3) If ``attendee_name`` is empty, it may automatically fall
back to values from a parent product or from invoice addresses.
back to values from a parent product or from invoice addresses. (4) Additional properties
``order__status``, ``order__valid_if_pending``, ``order__require_approval``, and
``order__locale`` are included with details form the order for convenience.
:>json boolean require_attention: Whether or not the ``require_attention`` flag is set on the item or order.
:>json list checkin_texts: List of additional texts to show to the user.
:>json object list: Excerpt of information about the matching :ref:`check-in list <rest-checkinlists>` (if any was found),

View File

@@ -35,6 +35,10 @@ subevent_mode strings Determines h
``"same"`` (discount is only applied for groups within
the same date), or ``"distinct"`` (discount is only applied
for groups with no two same dates).
subevent_date_from datetime The first date time of a subevent to which this discount can be applied
(or ``null``). Ignored in non-series events.
subevent_date_until datetime The last date time of a subevent to which this discount can be applied
(or ``null``). Ignored in non-series events.
condition_all_products boolean If ``true``, the discount condition applies to all items.
condition_limit_products list of integers If ``condition_all_products`` is not set, this is a list
of internal item IDs that the discount condition applies to.
@@ -105,6 +109,8 @@ Endpoints
"available_from": null,
"available_until": null,
"subevent_mode": "mixed",
"subevent_date_from": null,
"subevent_date_until": null,
"condition_all_products": true,
"condition_limit_products": [],
"condition_apply_to_addons": true,
@@ -163,6 +169,8 @@ Endpoints
"available_from": null,
"available_until": null,
"subevent_mode": "mixed",
"subevent_date_from": null,
"subevent_date_until": null,
"condition_all_products": true,
"condition_limit_products": [],
"condition_apply_to_addons": true,
@@ -207,6 +215,8 @@ Endpoints
"available_from": null,
"available_until": null,
"subevent_mode": "mixed",
"subevent_date_from": null,
"subevent_date_until": null,
"condition_all_products": true,
"condition_limit_products": [],
"condition_apply_to_addons": true,
@@ -240,6 +250,8 @@ Endpoints
"available_from": null,
"available_until": null,
"subevent_mode": "mixed",
"subevent_date_from": null,
"subevent_date_until": null,
"condition_all_products": true,
"condition_limit_products": [],
"condition_apply_to_addons": true,
@@ -302,6 +314,8 @@ Endpoints
"available_from": null,
"available_until": null,
"subevent_mode": "mixed",
"subevent_date_from": null,
"subevent_date_until": null,
"condition_all_products": true,
"condition_limit_products": [],
"condition_apply_to_addons": true,

View File

@@ -54,7 +54,7 @@ dependencies = [
"django-redis==5.4.*",
"django-scopes==2.0.*",
"django-statici18n==2.6.*",
"djangorestframework==3.15.*",
"djangorestframework==3.16.*",
"dnspython==2.7.*",
"drf_ujson2==1.7.*",
"geoip2==5.*",

View File

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

View File

@@ -84,6 +84,7 @@ class CheckinRPCRedeemInputSerializer(serializers.Serializer):
type = serializers.ChoiceField(choices=Checkin.CHECKIN_TYPES, default=Checkin.TYPE_ENTRY)
ignore_unpaid = serializers.BooleanField(default=False, required=False)
questions_supported = serializers.BooleanField(default=True, required=False)
use_order_locale = serializers.BooleanField(default=False, required=False)
nonce = serializers.CharField(required=False, allow_null=True)
datetime = serializers.DateTimeField(required=False, allow_null=True)
answers = serializers.JSONField(required=False, allow_null=True)

View File

@@ -38,11 +38,12 @@ class DiscountSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
class Meta:
model = Discount
fields = ('id', 'active', 'internal_name', 'position', 'all_sales_channels', 'limit_sales_channels',
'available_from', 'available_until', 'subevent_mode', 'condition_all_products',
'condition_limit_products', 'condition_apply_to_addons', 'condition_min_count', 'condition_min_value',
'benefit_discount_matching_percent', 'benefit_only_apply_to_cheapest_n_matches',
'benefit_same_products', 'benefit_limit_products', 'benefit_apply_to_addons',
'benefit_ignore_voucher_discounted', 'condition_ignore_voucher_discounted')
'available_from', 'available_until', 'subevent_mode', 'subevent_date_from', 'subevent_date_until',
'condition_all_products', 'condition_limit_products', 'condition_apply_to_addons',
'condition_min_count', 'condition_min_value', 'benefit_discount_matching_percent',
'benefit_only_apply_to_cheapest_n_matches', 'benefit_same_products', 'benefit_limit_products',
'benefit_apply_to_addons', 'benefit_ignore_voucher_discounted',
'condition_ignore_voucher_discounted')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@@ -607,6 +607,7 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
order__status = serializers.SlugRelatedField(read_only=True, slug_field='status', source='order')
order__valid_if_pending = serializers.SlugRelatedField(read_only=True, slug_field='valid_if_pending', source='order')
order__require_approval = serializers.SlugRelatedField(read_only=True, slug_field='require_approval', source='order')
order__locale = serializers.SlugRelatedField(read_only=True, slug_field='locale', source='order')
class Meta:
model = OrderPosition
@@ -615,7 +616,7 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
'print_logs', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat',
'require_attention', 'order__status', 'order__valid_if_pending', 'order__require_approval',
'valid_from', 'valid_until', 'blocked')
'order__locale', 'valid_from', 'valid_until', 'blocked')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -1518,7 +1519,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
self.context['event'],
order.sales_channel,
[
(cp.item_id, cp.subevent_id, cp.price, bool(cp.addon_to), cp.is_bundled, pos._voucher_discount)
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.price,
bool(cp.addon_to), cp.is_bundled, pos._voucher_discount)
for cp in order_positions
]
)

View File

@@ -420,7 +420,7 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force, checkin_type, ignore_unpaid, nonce,
untrusted_input, user, auth, expand, pdf_data, request, questions_supported, canceled_supported,
source_type='barcode', legacy_url_support=False, simulate=False, gate=None):
source_type='barcode', legacy_url_support=False, simulate=False, gate=None, use_order_locale=False):
if not checkinlists:
raise ValidationError('No check-in list passed.')
@@ -694,7 +694,11 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
pass
# 6. Pass to our actual check-in logic
with language(op.order.event.settings.locale):
if use_order_locale:
locale = op.order.locale
else:
locale = op.order.event.settings.locale
with language(locale):
try:
perform_checkin(
op=op,
@@ -909,6 +913,7 @@ class CheckinRPCRedeemView(views.APIView):
expand=self.request.query_params.getlist('expand'),
pdf_data=self.request.query_params.get('pdf_data', 'false') == 'true',
questions_supported=s.validated_data['questions_supported'],
use_order_locale=s.validated_data['use_order_locale'],
canceled_supported=True,
request=self.request, # this is not clean, but we need it in the serializers for URL generation
legacy_url_support=False,

View File

@@ -185,7 +185,7 @@ with scopes_disabled():
| Q(full_invoice_no__iexact=u)
).values_list('order_id', flat=True)
matching_positions = OrderPosition.objects.filter(
matching_positions = OrderPosition.all.filter(
Q(order=OuterRef('pk')) & Q(
Q(attendee_name_cached__icontains=u) | Q(attendee_email__icontains=u)
| Q(secret__istartswith=u)

View File

@@ -127,7 +127,13 @@ class NamePartsWidget(forms.MultiWidget):
if fname == 'title' and self.titles:
widgets.append(Select(attrs=a, choices=[('', '')] + [(d, d) for d in self.titles[1]]))
elif fname == 'salutation':
widgets.append(Select(attrs=a, choices=[('', '---'), ('empty', '')] + PERSON_NAME_SALUTATIONS))
widgets.append(Select(
attrs=a,
choices=[
('', '---'),
('empty', '({})'.format(pgettext_lazy("name_salutation", "not specified"))),
] + PERSON_NAME_SALUTATIONS
))
else:
widgets.append(self.widget(attrs=a))
super().__init__(widgets, attrs)
@@ -245,7 +251,10 @@ class NamePartsFormField(forms.MultiValueField):
d.pop('validators', None)
field = forms.ChoiceField(
**d,
choices=[('', '---'), ('empty', '')] + PERSON_NAME_SALUTATIONS
choices=[
('', '---'),
('empty', '({})'.format(pgettext_lazy("name_salutation", "not specified"))),
] + PERSON_NAME_SALUTATIONS
)
else:
field = forms.CharField(**defaults)

View File

@@ -0,0 +1,23 @@
# Generated by Django 4.2.19 on 2025-03-18 09:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0278_login_source_add_unique_together'),
]
operations = [
migrations.AddField(
model_name='discount',
name='subevent_date_from',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='discount',
name='subevent_date_until',
field=models.DateTimeField(blank=True, null=True),
),
]

View File

@@ -36,7 +36,9 @@ from django_scopes import ScopedManager
from pretix.base.decimal import round_decimal
from pretix.base.models.base import LoggedModel
PositionInfo = namedtuple('PositionInfo', ['item_id', 'subevent_id', 'line_price_gross', 'is_addon_to', 'voucher_discount'])
PositionInfo = namedtuple('PositionInfo',
['item_id', 'subevent_id', 'subevent_date_from', 'line_price_gross', 'is_addon_to',
'voucher_discount'])
class Discount(LoggedModel):
@@ -171,6 +173,17 @@ class Discount(LoggedModel):
"access to sold-out quota will still receive the discount."),
)
subevent_date_from = models.DateTimeField(
verbose_name=pgettext_lazy("subevent", "Available for dates starting from"),
null=True,
blank=True,
)
subevent_date_until = models.DateTimeField(
verbose_name=pgettext_lazy("subevent", "Available for dates starting until"),
null=True,
blank=True,
)
# more feature ideas:
# - max_usages_per_order
# - promote_to_user_if_almost_satisfied
@@ -355,11 +368,15 @@ class Discount(LoggedModel):
# First, filter out everything not even covered by our product scope
condition_candidates = [
idx
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount) in positions.items()
for idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount) in
positions.items()
if (
(self.condition_all_products or item_id in limit_products) and
(self.condition_apply_to_addons or not is_addon_to) and
(not self.condition_ignore_voucher_discounted or voucher_discount is None or voucher_discount == Decimal('0.00'))
and (not subevent_id or (
self.subevent_date_from is None or subevent_date_from >= self.subevent_date_from)) and (
self.subevent_date_until is None or subevent_date_from <= self.subevent_date_until)
)
]
@@ -369,7 +386,8 @@ class Discount(LoggedModel):
benefit_products = {p.pk for p in self.benefit_limit_products.all()}
benefit_candidates = [
idx
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount) in positions.items()
for idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount) in
positions.items()
if (
item_id in benefit_products and
(self.benefit_apply_to_addons or not is_addon_to) and

View File

@@ -1398,7 +1398,8 @@ class CartManager:
self.event,
self._sales_channel.identifier,
[
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
for cp in positions
]
)

View File

@@ -120,7 +120,8 @@ class CrossSellingService:
self.event,
self.sales_channel,
[
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled,
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
bool(cp.addon_to), cp.is_bundled,
cp.listed_price - cp.price_after_voucher)
for cp in self.cartpositions
],

View File

@@ -875,7 +875,8 @@ def _check_positions(event: Event, now_dt: datetime, time_machine_now_dt: dateti
event,
sales_channel.identifier,
[
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
for cp in sorted_positions
]
)
@@ -2308,7 +2309,7 @@ class OrderChangeManager:
op.position.tax_rate = op.price.rate
op.position.tax_value = op.price.tax
op.position.tax_code = op.price.code
op.position.save()
op.position.save(update_fields=['price', 'tax_rate', 'tax_value', 'tax_code'])
elif isinstance(op, self.TaxRuleOperation):
if isinstance(op.position, OrderPosition):
self.order.log_action('pretix.event.order.changed.tax_rule', user=self.user, auth=self.auth, data={

View File

@@ -21,6 +21,7 @@
#
import re
from collections import defaultdict
from datetime import datetime
from decimal import Decimal
from typing import List, Optional, Tuple, Union
@@ -162,14 +163,14 @@ def get_line_price(price_after_voucher: Decimal, custom_price_input: Decimal, cu
def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
positions: List[Tuple[int, Optional[int], Decimal, bool, bool, Decimal]],
positions: List[Tuple[int, Optional[int], Optional[datetime], Decimal, bool, bool, Decimal]],
collect_potential_discounts: Optional[defaultdict]=None) -> List[Tuple[Decimal, Optional[Discount]]]:
"""
Applies any dynamic discounts to a cart
:param event: Event the cart belongs to
:param sales_channel: Sales channel the cart was created with
:param positions: Tuple of the form ``(item_id, subevent_id, line_price_gross, is_addon_to, is_bundled, voucher_discount)``
:param positions: Tuple of the form ``(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)``
:param collect_potential_discounts: If a `defaultdict(list)` is supplied, all discounts that could be applied to the cart
based on the "consumed" items, but lack matching "benefitting" items will be collected therein.
The dict will contain a mapping from index in the `positions` list of the item that could be consumed, to a list
@@ -191,12 +192,14 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
).prefetch_related('condition_limit_products', 'benefit_limit_products').order_by('position', 'pk')
for discount in discount_qs:
result = discount.apply({
idx: PositionInfo(item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount)
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, is_bundled, voucher_discount) in enumerate(positions)
idx: PositionInfo(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount)
for
idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
in enumerate(positions)
if not is_bundled and idx not in new_prices
}, collect_potential_discounts)
for k in result.keys():
result[k] = (result[k], discount)
new_prices.update(result)
return [new_prices.get(idx, (p[2], None)) for idx, p in enumerate(positions)]
return [new_prices.get(idx, (p[3], None)) for idx, p in enumerate(positions)]

View File

@@ -134,13 +134,13 @@ def order_overview(
qs = qs.filter(item__admission=True)
items = items.filter(admission=True)
if date_from and isinstance(date_from, date):
if date_from and isinstance(date_from, date) and not isinstance(date_from, datetime):
date_from = make_aware(datetime.combine(
date_from,
time(hour=0, minute=0, second=0, microsecond=0)
), event.timezone)
if date_until and isinstance(date_until, date):
if date_until and isinstance(date_until, date) and not isinstance(date_until, datetime):
date_until = make_aware(datetime.combine(
date_until + timedelta(days=1),
time(hour=0, minute=0, second=0, microsecond=0)

View File

@@ -3705,7 +3705,7 @@ COUNTRIES_WITH_STATE_IN_ADDRESS = {
# are actually *used* in postal addresses. This is obviously not complete and opinionated.
# Country: [(List of subdivision types as defined by pycountry), (short or long form to be used)]
'AU': (['State', 'Territory'], 'short'),
'BR': (['State'], 'short'),
'BR': (['Federal district', 'State'], 'short'),
'CA': (['Province', 'Territory'], 'short'),
# 'CN': (['Province', 'Autonomous region', 'Munincipality'], 'long'),
'JP': (['Prefecture'], 'long'),

View File

@@ -0,0 +1,5 @@
<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>

After

Width:  |  Height:  |  Size: 636 B

View File

@@ -45,6 +45,8 @@ class DiscountForm(I18nModelForm):
'limit_sales_channels',
'available_from',
'available_until',
'subevent_date_from',
'subevent_date_until',
'subevent_mode',
'condition_all_products',
'condition_limit_products',
@@ -62,6 +64,8 @@ class DiscountForm(I18nModelForm):
field_classes = {
'available_from': SplitDateTimeField,
'available_until': SplitDateTimeField,
'subevent_date_from': SplitDateTimeField,
'subevent_date_until': SplitDateTimeField,
'condition_limit_products': ItemMultipleChoiceField,
'benefit_limit_products': ItemMultipleChoiceField,
'limit_sales_channels': SafeModelMultipleChoiceField,
@@ -70,6 +74,8 @@ class DiscountForm(I18nModelForm):
'subevent_mode': forms.RadioSelect,
'available_from': SplitDateTimePickerWidget(),
'available_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_available_from_0'}),
'subevent_date_from': SplitDateTimePickerWidget(),
'subevent_date_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_subevent_date_from_0'}),
'condition_limit_products': forms.CheckboxSelectMultiple(attrs={
'data-inverse-dependency': '<[name$=all_products]',
'class': 'scrolling-multiple-choice',

View File

@@ -267,7 +267,7 @@ class OrderFilterForm(FilterForm):
Q(invoice_no__in=invoice_nos)
| Q(full_invoice_no__iexact=u)
).values_list('order_id', flat=True)
matching_positions = OrderPosition.objects.filter(
matching_positions = OrderPosition.all.filter(
Q(
Q(attendee_name_cached__icontains=u) | Q(attendee_email__icontains=u)
| Q(company__icontains=u)

View File

@@ -26,6 +26,8 @@
{% bootstrap_field form.condition_ignore_voucher_discounted layout="control" %}
{% if form.subevent_mode %}
{% bootstrap_field form.subevent_mode layout="control" %}
{% bootstrap_field form.subevent_date_from layout="control" %}
{% bootstrap_field form.subevent_date_until layout="control" %}
{% endif %}
<div class="form-group form-alternatives">
<label class="col-md-3 control-label">

View File

@@ -40,6 +40,7 @@
<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>
@@ -111,6 +112,14 @@
<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,10 +413,7 @@
{% endif %}
{% if line.seat %}
<br />
<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>
{% include "icons/seat.svg" with cls="svg-icon" %}
{{ line.seat }}
{% endif %}
{% if line.voucher %}

View File

@@ -182,8 +182,54 @@
</div>
</div>
{% endif %}
<div class="row control-group pdf-info">
<div class="col-sm-12">
<label for="pdf-info-locale">{% trans "Preferred language" %}</label><br>
<select class="form-control" id="pdf-info-locale">
<option value="">{% trans "Order locale" %}</option>
{% for l in locales %}
<option value="{{ l.0 }}">{{ l.1 }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row control-group pdf-info">
<hr/>
<div class="col-sm-12">
<label>{% trans "Upload PDF as background" %}</label>
<p class="text-muted">
{% blocktrans trimmed %}
You can upload a PDF to use as a custom background.
The paper size will match the PDF.
{% endblocktrans %}
</p>
<p>
<span class="btn btn-default fileinput-button background-button btn-block">
<i class="fa fa-upload"></i>
<span>{% trans "Upload PDF as background" %}</span>
<input id="fileupload" type="file" name="background" accept="application/pdf">
</span>
</p>
<p class="text-center">
<a class="btn btn-link background-download-button" href="{{ pdf }}" target="_blank">
<i class="fa fa-download"></i>
<span class="small">{% trans "Download current background" %}</span>
</a>
</p>
</div>
</div>
<div class="row control-group pdf-info">
<div class="col-sm-12">
<label>{% trans "Or choose custom paper size" %}</label>
<p class="text-muted">
{% blocktrans trimmed %}
To manually change the paper size, you need to create a new, empty background.
{% endblocktrans %}
</p>
</div>
</div>
<div class="row control-group pdf-info">
<div class="col-sm-6">
<label for="pdf-info-width">{% trans "Width (mm)" %}</label><br>
<input type="number" id="pdf-info-width" class="input-block-level form-control">
@@ -195,45 +241,12 @@
</div>
<div class="row control-group pdf-info">
<div class="col-sm-12">
<label>{% trans "Background PDF" %}</label><br>
<p>
<button class="btn btn-default background-button" id="pdf-empty">
<button class="btn btn-default background-button btn-block" id="pdf-empty">
<i class="fa fa-file-o"></i>
{% trans "Create empty background" %}
</button>
</p>
<span class="btn btn-default fileinput-button background-button">
<i class="fa fa-upload"></i>
<span>{% trans "Upload custom background" %}</span>
<input id="fileupload" type="file" name="background" accept="application/pdf">
</span>
</div>
<div class="col-sm-12 help-inline">
<p>
{% blocktrans trimmed %}
After you changed the page size, you need to create a new empty background. If you
want to use a custom background, it already needs to have the correct size.
{% endblocktrans %}
</p>
</div>
<div class="col-sm-12">
<p>
<a class="btn btn-default background-download-button" href="{{ pdf }}" target="_blank">
<i class="fa fa-download"></i>
<span>{% trans "Download current background" %}</span>
</a>
</p>
</div>
</div>
<div class="row control-group pdf-info">
<hr/>
<div class="col-sm-12">
<label for="pdf-info-locale">{% trans "Preferred language" %}</label><br>
<select class="form-control" id="pdf-info-locale">
<option value="">{% trans "Order locale" %}</option>
{% for l in locales %}
<option value="{{ l.0 }}">{{ l.1 }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row control-group poweredby">

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, Voucher,
QuestionAnswer, QuestionOption, Quota, SeatCategoryMapping, Voucher,
)
from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
@@ -101,10 +101,16 @@ 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')
var_count=Count('variations'),
requires_seat=requires_seat,
).prefetch_related("category", "limit_sales_channels").order_by(
F('category__position').asc(nulls_first=True),
'category', 'position'

View File

@@ -44,7 +44,9 @@ import dateutil
from django import forms
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.exceptions import (
BadRequest, PermissionDenied, ValidationError,
)
from django.core.files import File
from django.db import transaction
from django.db.models import (
@@ -944,13 +946,16 @@ class DeviceQueryMixin:
qs = self.request.organizer.devices.prefetch_related(
'limit_events', 'gate',
).order_by('revoked', '-device_id')
if self.filter_form.is_valid():
qs = self.filter_form.filter_qs(qs)
if 'device' in self.request_data and '__ALL' not in self.request_data:
qs = qs.filter(
id__in=self.request_data.getlist('device')
)
elif self.request.method == 'GET' or '__ALL' in self.request_data:
if self.filter_form.is_valid():
qs = self.filter_form.filter_qs(qs)
else:
raise BadRequest("No devices selected")
return qs

View File

@@ -37,7 +37,7 @@ from zoneinfo import ZoneInfo
from dateutil.parser import parse
from django.core.exceptions import PermissionDenied
from django.db.models import F, Max, Min, Q
from django.db.models import Count, F, Max, Min, Q
from django.db.models.functions import Coalesce, Greatest
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
@@ -326,6 +326,9 @@ def nav_context_list(request):
qs_orga = Organizer.objects.filter(pk__in=request.user.teams.values_list('organizer', flat=True))
if query:
qs_orga = qs_orga.filter(Q(name__icontains=query) | Q(slug__icontains=query))
qs_orga = qs_orga.annotate(
n_events=Count("events")
).order_by("-n_events")
if query and len(query) >= 3:
qs_orders = Order.objects.filter(

View File

@@ -33,7 +33,10 @@
# License for the specific language governing permissions and limitations under the License.
from django.utils.html import format_html
from django.utils.translation import get_language, gettext_lazy as _
from django.utils.safestring import mark_safe
from django.utils.translation import (
get_language, gettext_lazy as _, pgettext_lazy,
)
from pretix.helpers.templatetags.date_fast import date_fast as _date
@@ -48,23 +51,28 @@ def daterange(df, dt, as_html=False):
else:
if as_html:
base_format = format_html("<time datetime=\"{}\">{{}}</time>{{}}<time datetime=\"{}\">{{}}</time>", _date(df, "Y-m-d"), _date(dt, "Y-m-d"))
until = format_html(
" <span aria-hidden=\"true\"></span><span class=\"sr-only\"> {until} </span> ",
until=pgettext_lazy("timerange", "until")
)
else:
base_format = "{}{}{}"
until = " "
if lng.startswith("de"):
if df.year == dt.year and df.month == dt.month and df.day == dt.day:
return format_html(base_format, _date(df, "D, j. F Y"))
elif df.year == dt.year and df.month == dt.month:
return format_html(base_format, _date(df, "j."), "", _date(dt, "j. F Y"))
return format_html(base_format, _date(df, "j."), mark_safe(until.strip()), _date(dt, "j. F Y"))
elif df.year == dt.year:
return format_html(base_format, _date(df, "j. F"), " ", _date(dt, "j. F Y"))
return format_html(base_format, _date(df, "j. F"), until, _date(dt, "j. F Y"))
elif lng.startswith("en"):
if df.year == dt.year and df.month == dt.month and df.day == dt.day:
return format_html(base_format, _date(df, "D, N jS, Y"))
elif df.year == dt.year and df.month == dt.month:
return format_html(base_format, _date(df, "N jS"), " ", _date(dt, "jS, Y"))
return format_html(base_format, _date(df, "N jS"), until, _date(dt, "jS, Y"))
elif df.year == dt.year:
return format_html(base_format, _date(df, "N jS"), " ", _date(dt, "N jS, Y"))
return format_html(base_format, _date(df, "N jS"), until, _date(dt, "N jS, Y"))
elif lng.startswith("es"):
if df.year == dt.year and df.month == dt.month and df.day == dt.day:
return format_html(base_format, _date(df, "DATE_FORMAT"))
@@ -72,14 +80,14 @@ def daterange(df, dt, as_html=False):
return format_html(
base_format,
_date(df, "j"),
" - ",
until,
"{} de {} de {}".format(_date(dt, "j"), _date(dt, "F"), _date(dt, "Y"))
)
elif df.year == dt.year:
return format_html(
base_format,
"{} de {}".format(_date(df, "j"), _date(df, "F")),
" - ",
until,
"{} de {} de {}".format(_date(dt, "j"), _date(dt, "F"), _date(dt, "Y"))
)
@@ -89,24 +97,31 @@ def daterange(df, dt, as_html=False):
if as_html:
base_format = "<time datetime=\"{}\">{}</time>"
return format_html(
"{date_from} {date_to}",
"{date_from}{until}{date_to}",
date_from=format_html(base_format, _date(df, "Y-m-d"), _date(df, "DATE_FORMAT")),
date_to=format_html(base_format, _date(dt, "Y-m-d"), _date(dt, "DATE_FORMAT")),
until=until,
)
return _("{date_from} {date_to}").format(
return _("{date_from}{until}{date_to}").format(
date_from=_date(df, "DATE_FORMAT"),
date_to=_date(dt, "DATE_FORMAT"),
until=until,
)
def datetimerange(df, dt, as_html=False):
if as_html:
base_format = format_html("<time datetime=\"{}\">{{}}</time>{{}}<time datetime=\"{}\">{{}}</time>", _date(df, "Y-m-d H:i"), _date(dt, "Y-m-d H:i"))
until = format_html(
" <span aria-hidden=\"true\"></span><span class=\"sr-only\"> {until} </span> ",
until=pgettext_lazy("timerange", "until")
)
else:
base_format = "{}{}{}"
until = " "
if df.year == dt.year and df.month == dt.month and df.day == dt.day:
return format_html(base_format, _date(df, "SHORT_DATE_FORMAT") + " " + _date(df, "TIME_FORMAT"), " ", _date(dt, "TIME_FORMAT"))
return format_html(base_format, _date(df, "SHORT_DATE_FORMAT") + " " + _date(df, "TIME_FORMAT"), until, _date(dt, "TIME_FORMAT"))
else:
return format_html(base_format, _date(df, "SHORT_DATETIME_FORMAT"), " ", _date(dt, "SHORT_DATETIME_FORMAT"))
return format_html(base_format, _date(df, "SHORT_DATETIME_FORMAT"), until, _date(dt, "SHORT_DATETIME_FORMAT"))

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 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 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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 668 B

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:44+0000\n"
"PO-Revision-Date: 2025-03-19 01:00+0000\n"
"Last-Translator: Hector <hector@alpakafest.com>\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"
"Language: 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.10.3\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -12111,18 +12111,14 @@ msgid "MA"
msgstr "Ma"
#: pretix/base/settings.py:3720 pretix/base/settings.py:3722
#, fuzzy
#| msgid "Provider name"
msgctxt "address"
msgid "Province"
msgstr "Nombre del proveedor"
msgstr "Provincia"
#: pretix/base/settings.py:3721
#, fuzzy
#| msgid "Use feature"
msgctxt "address"
msgid "Prefecture"
msgstr "Función de uso"
msgstr "Prefectura"
#: pretix/base/settings.py:3810 pretix/control/forms/event.py:228
msgid ""
@@ -14713,6 +14709,9 @@ msgid ""
"only use characters A-Z, a-z, 0-9, and common special characters "
"({characters})."
msgstr ""
"La contraseña contiene caracteres no admitidos por nuestro sistema de correo "
"electrónico. Por favor, utilice sólo caracteres A-Z, a-z, 0-9 y caracteres "
"especiales comunes ({characters})."
#: pretix/control/forms/mailsetup.py:70
msgid "Use STARTTLS"
@@ -15074,10 +15073,9 @@ msgid "Recipient"
msgstr "Destinatario"
#: pretix/control/forms/orders.py:768
#, fuzzy, python-brace-format
#| msgid "Attach ticket files"
#, python-brace-format
msgid "Attach {file}"
msgstr "Adjuntar archivos de entradas"
msgstr "Adjuntar {file}"
#: pretix/control/forms/orders.py:796
msgid ""
@@ -17872,13 +17870,7 @@ msgid "Delete check-ins"
msgstr "Eliminar los check-in"
#: pretix/control/templates/pretixcontrol/checkin/bulk_revert_confirm.html:15
#, fuzzy, python-format
#| msgid ""
#| "Are you sure you want to permanently delete the check-ins of <strong>one "
#| "ticket</strong>."
#| msgid_plural ""
#| "Are you sure you want to permanently delete the check-ins of "
#| "<strong>%(count)s tickets</strong>?"
#, python-format
msgid ""
"Are you sure you want to permanently delete the check-ins of <strong>one "
"ticket</strong>?"
@@ -17886,8 +17878,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>?"
@@ -19428,10 +19420,8 @@ msgid "Disabled"
msgstr "Deshabilitado"
#: pretix/control/templates/pretixcontrol/event/payment.html:57
#, fuzzy
#| msgid "Enable waiting list"
msgid "Enable additional payment plugins"
msgstr "Habilitar lista de espera"
msgstr "Habilitar plugins de pago adicionales"
#: pretix/control/templates/pretixcontrol/event/payment.html:66
msgid "Deadlines"
@@ -19531,10 +19521,8 @@ msgid "Your changes have been saved."
msgstr "Los cambios se han guardado."
#: pretix/control/templates/pretixcontrol/event/plugins.html:34
#, fuzzy
#| msgid "Check results"
msgid "Search results"
msgstr "Comprobar resultados"
msgstr "Resultados de la búsqueda"
#: pretix/control/templates/pretixcontrol/event/plugins.html:56
msgid "Top recommendation"
@@ -19554,16 +19542,12 @@ msgstr "No disponible"
#: pretix/control/templates/pretixcontrol/event/plugins.html:93
#: pretix/control/templates/pretixcontrol/event/plugins.html:105
#, fuzzy
#| msgid "Login settings"
msgid "Open plugin settings"
msgstr "Configuración de inicio de sesión"
msgstr "Abrir la configuración del plugin"
#: pretix/control/templates/pretixcontrol/event/plugins.html:94
#, fuzzy
#| msgid "Go to shop"
msgid "Go to"
msgstr "Ir a la tienda"
msgstr "Ir a"
#: pretix/control/templates/pretixcontrol/event/plugins.html:116
#: pretix/control/templates/pretixcontrol/oauth/app_delete.html:15
@@ -22431,11 +22415,8 @@ msgid "Subject:"
msgstr "Asunto:"
#: pretix/control/templates/pretixcontrol/order/mail_history.html:59
#, fuzzy
#| msgctxt "attachment_filename"
#| msgid "Calendar invite"
msgid "Calendar invite"
msgstr "Invitación al calendario"
msgstr "Invitación para el calendario"
#: pretix/control/templates/pretixcontrol/order/pay.html:5
#: pretix/control/templates/pretixcontrol/order/pay.html:9
@@ -26473,13 +26454,11 @@ msgstr "Funciones API"
#: pretix/control/views/event.py:444
msgid "The plugin {} is now active, you can configure it here:"
msgstr ""
msgstr "El plugin {} está ahora activo, puede configurarlo aquí:"
#: pretix/control/views/event.py:453
#, fuzzy
#| msgid "The relevant plugin is currently not active."
msgid "The plugin {} is now active."
msgstr "El plugin correspondiente no está activado."
msgstr "El plugin {} ya está activo."
#: pretix/control/views/event.py:516
msgid ""
@@ -26962,11 +26941,9 @@ msgid "Access for the selected application has been revoked."
msgstr "Se ha revocado el acceso a la aplicación seleccionada."
#: pretix/control/views/orders.py:192
#, fuzzy
#| msgid "We could not save your changes. See below for details."
msgid "We could not process your input. See below for details."
msgstr ""
"No se han podido guardar los cambios. Consulta los detalles a continuación."
"No hemos podido procesar su entrada. Consulta los detalles a continuación."
#: pretix/control/views/orders.py:265
#, python-brace-format
@@ -32038,10 +32015,8 @@ msgstr ""
"conexión a Internet decente."
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:14
#, fuzzy
#| msgid "Open Layout Designer"
msgid "Open layout editor"
msgstr "Abrir herramienta de diseño"
msgstr "Abrir el editor de diseño"
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:18
msgid "Advanced mode (multiple layouts)"

View File

@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:46+0000\n"
"PO-Revision-Date: 2025-01-21 00:00+0000\n"
"Last-Translator: Hector <hector@demandaeventos.es>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
"js/es/>\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: 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.9.2\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
@@ -188,7 +188,7 @@ msgstr "Cambiar lista de registro"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
msgid "Search results"
msgstr "Resultados de búsqueda"
msgstr "Resultados de la búsqueda"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
msgid "No tickets found"
@@ -684,10 +684,8 @@ msgid "Calculating default price…"
msgstr "Calculando el precio por defecto…"
#: pretix/static/pretixcontrol/js/ui/plugins.js:69
#, fuzzy
#| msgid "Search results"
msgid "No results"
msgstr "Resultados de búsqueda"
msgstr "No hay resultados"
#: pretix/static/pretixcontrol/js/ui/question.js:42
msgid "Others"

View File

@@ -4,7 +4,7 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:44+0000\n"
"PO-Revision-Date: 2025-03-17 17: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/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.10.3\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -12238,18 +12238,14 @@ msgid "MA"
msgstr "MA"
#: pretix/base/settings.py:3720 pretix/base/settings.py:3722
#, fuzzy
#| msgid "Provider name"
msgctxt "address"
msgid "Province"
msgstr "Nom du fournisseur"
msgstr "Province"
#: pretix/base/settings.py:3721
#, fuzzy
#| msgid "Use feature"
msgctxt "address"
msgid "Prefecture"
msgstr "Utiliser la fonction"
msgstr "Préfecture"
#: pretix/base/settings.py:3810 pretix/control/forms/event.py:228
msgid ""
@@ -14846,6 +14842,9 @@ msgid ""
"only use characters A-Z, a-z, 0-9, and common special characters "
"({characters})."
msgstr ""
"Le mot de passe contient des caractères qui ne sont pas pris en charge par "
"notre système de messagerie. Veuillez utiliser uniquement les caractères A-"
"Z, a-z, 0-9 et les caractères spéciaux courants ({characters})."
#: pretix/control/forms/mailsetup.py:70
msgid "Use STARTTLS"
@@ -15209,10 +15208,9 @@ msgid "Recipient"
msgstr "Destinataire"
#: pretix/control/forms/orders.py:768
#, fuzzy, python-brace-format
#| msgid "Attach ticket files"
#, python-brace-format
msgid "Attach {file}"
msgstr "Joindre les fichiers de tickets"
msgstr "Joindre {file}"
#: pretix/control/forms/orders.py:796
msgid ""
@@ -18007,13 +18005,7 @@ msgid "Delete check-ins"
msgstr "Supprimer les enregistrements"
#: pretix/control/templates/pretixcontrol/checkin/bulk_revert_confirm.html:15
#, fuzzy, python-format
#| msgid ""
#| "Are you sure you want to permanently delete the check-ins of <strong>one "
#| "ticket</strong>."
#| msgid_plural ""
#| "Are you sure you want to permanently delete the check-ins of "
#| "<strong>%(count)s tickets</strong>?"
#, python-format
msgid ""
"Are you sure you want to permanently delete the check-ins of <strong>one "
"ticket</strong>?"
@@ -19572,10 +19564,8 @@ msgid "Disabled"
msgstr "Désactivé"
#: pretix/control/templates/pretixcontrol/event/payment.html:57
#, fuzzy
#| msgid "Enable waiting list"
msgid "Enable additional payment plugins"
msgstr "Activer la liste d'attente"
msgstr "Activer des plugins de paiement supplémentaires"
#: pretix/control/templates/pretixcontrol/event/payment.html:66
msgid "Deadlines"
@@ -19680,10 +19670,8 @@ msgid "Your changes have been saved."
msgstr "Vos modifications ont été enregistrées."
#: pretix/control/templates/pretixcontrol/event/plugins.html:34
#, fuzzy
#| msgid "Check results"
msgid "Search results"
msgstr "Vérifier les résultats"
msgstr "Résultats de la recherche"
#: pretix/control/templates/pretixcontrol/event/plugins.html:56
msgid "Top recommendation"
@@ -19703,16 +19691,12 @@ msgstr "Non disponible"
#: pretix/control/templates/pretixcontrol/event/plugins.html:93
#: pretix/control/templates/pretixcontrol/event/plugins.html:105
#, fuzzy
#| msgid "Login settings"
msgid "Open plugin settings"
msgstr "Paramètres de connexion"
msgstr "Ouvrir les paramètres du plugin"
#: pretix/control/templates/pretixcontrol/event/plugins.html:94
#, fuzzy
#| msgid "Go to shop"
msgid "Go to"
msgstr "Accéder à la boutique"
msgstr "Aller à"
#: pretix/control/templates/pretixcontrol/event/plugins.html:116
#: pretix/control/templates/pretixcontrol/oauth/app_delete.html:15
@@ -22598,11 +22582,8 @@ msgid "Subject:"
msgstr "Sujet :"
#: pretix/control/templates/pretixcontrol/order/mail_history.html:59
#, fuzzy
#| msgctxt "attachment_filename"
#| msgid "Calendar invite"
msgid "Calendar invite"
msgstr "Invitation au calendrier"
msgstr "Invitation à l'agenda"
#: pretix/control/templates/pretixcontrol/order/pay.html:5
#: pretix/control/templates/pretixcontrol/order/pay.html:9
@@ -26677,13 +26658,11 @@ msgstr "Fonctionnalités de lAPI"
#: pretix/control/views/event.py:444
msgid "The plugin {} is now active, you can configure it here:"
msgstr ""
msgstr "Le plugin {} est maintenant actif, vous pouvez le configurer ici :"
#: pretix/control/views/event.py:453
#, fuzzy
#| msgid "The relevant plugin is currently not active."
msgid "The plugin {} is now active."
msgstr "Le plugin correspondant n'est pas acti."
msgstr "Le plugin {} est maintenant actif."
#: pretix/control/views/event.py:516
msgid ""
@@ -27171,12 +27150,10 @@ msgid "Access for the selected application has been revoked."
msgstr "Laccès à lapplication sélectionnée a été révoqué."
#: pretix/control/views/orders.py:192
#, fuzzy
#| msgid "We could not save your changes. See below for details."
msgid "We could not process your input. See below for details."
msgstr ""
"Nous n'avons pas pu enregistrer vos modifications. Voir ci-dessous pour plus "
"de détails."
"Nous n'avons pas pu traiter votre demande. Voir ci-dessous pour plus de "
"détails."
#: pretix/control/views/orders.py:265
#, python-brace-format
@@ -32299,10 +32276,8 @@ msgstr ""
"moderne et une connexion Internet décente."
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:14
#, fuzzy
#| msgid "Open Layout Designer"
msgid "Open layout editor"
msgstr "Ouvrir l'outil de mise en page"
msgstr "Ouvrir l'éditeur de mise en page"
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:18
msgid "Advanced mode (multiple layouts)"

View File

@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: French\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:46+0000\n"
"PO-Revision-Date: 2025-01-16 10:32+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.9.2\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
@@ -187,7 +187,7 @@ msgstr "Changer de liste d'enregistrement"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
msgid "Search results"
msgstr "Résultats de recherche"
msgstr "Résultats de la recherche"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
msgid "No tickets found"
@@ -685,10 +685,8 @@ msgid "Calculating default price…"
msgstr "Calcul du prix par défaut …"
#: pretix/static/pretixcontrol/js/ui/plugins.js:69
#, fuzzy
#| msgid "Search results"
msgid "No results"
msgstr "Résultats de recherche"
msgstr "Aucun résultat"
#: pretix/static/pretixcontrol/js/ui/question.js:42
msgid "Others"

View File

@@ -7,16 +7,16 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:44+0000\n"
"PO-Revision-Date: 2025-03-11 15:09+0000\n"
"Last-Translator: MaartenUreel <maarten@ureel.be>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/"
">\n"
"PO-Revision-Date: 2025-03-30 16:00+0000\n"
"Last-Translator: Jan Van Haver <jan.van.haver@gmail.com>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/>"
"\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.2\n"
"X-Generator: Weblate 5.10.4\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -1592,7 +1592,7 @@ msgstr "Belastingwaarde"
#: pretix/plugins/reports/exporters.py:793
#: pretix/plugins/reports/exporters.py:838
msgid "Tax rate"
msgstr "Btw-tarief"
msgstr "Belastingtarief"
#: pretix/base/exporters/invoices.py:325
msgid "Tax name"
@@ -2535,7 +2535,7 @@ msgstr "Bedrag"
#: pretix/plugins/reports/accountingreport.py:495
#: pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_confirm.html:29
msgid "Payment method"
msgstr "Betaalmethode"
msgstr "Betalingsmethode"
#: pretix/base/exporters/orderlist.py:1077
msgid "Matching ID"
@@ -3298,7 +3298,7 @@ msgstr "Aantal"
#: pretix/base/invoice.py:683 pretix/base/invoice.py:833
msgctxt "invoice"
msgid "Tax rate"
msgstr "Btw-tarief"
msgstr "Belastingtarief"
#: pretix/base/invoice.py:684
msgctxt "invoice"
@@ -3420,16 +3420,12 @@ msgstr ""
"hier om naar de plugin instellingen te gaan."
#: pretix/base/logentrytype_registry.py:53
#, fuzzy
#| msgid "The selected ticket shop is currently not available."
msgid "The relevant plugin is currently not active."
msgstr "De geselecteerde ticketwinkel is op dit moment niet beschikbaar."
msgstr "De relevante plugin is op dit moment niet beschikbaar."
#: pretix/base/logentrytypes.py:49
#, fuzzy
#| msgid "Delete"
msgid "(deleted)"
msgstr "Verwijder"
msgstr "(verwijderd)"
#: pretix/base/logentrytypes.py:78
#, python-brace-format
@@ -4085,10 +4081,8 @@ msgid "Grant type"
msgstr "Soort subsidie"
#: pretix/base/models/customers.py:420
#, fuzzy
#| msgid "Required question"
msgid "Require PKCE extension"
msgstr "Verplichte vraag"
msgstr "PKCE-extensie verplicht"
#: pretix/base/models/customers.py:432
msgid "Allowed access scopes"
@@ -5993,10 +5987,8 @@ msgid "Insurance fee"
msgstr "Verzekeringskosten"
#: pretix/base/models/orders.py:2291
#, fuzzy
#| msgid "Other fees"
msgid "Late fee"
msgstr "Overige kosten"
msgstr "Kosten bij laattijdige betaling"
#: pretix/base/models/orders.py:2292
msgid "Other fees"
@@ -6244,10 +6236,8 @@ msgid "Seat {number}"
msgstr "Stoel {number}"
#: pretix/base/models/tax.py:144
#, fuzzy
#| msgid "Calendar invites"
msgid "Standard rates"
msgstr "Agenda-uitnodigingen"
msgstr "Standaard tarieven"
#: pretix/base/models/tax.py:148
msgctxt "tax_code"
@@ -6255,11 +6245,9 @@ msgid "Standard rate"
msgstr "Standaard tarief"
#: pretix/base/models/tax.py:152
#, fuzzy
#| msgid "Reduced ticket"
msgctxt "tax_code"
msgid "Reduced rate"
msgstr "Ticket met korting"
msgstr "Verminderd tarief"
#: pretix/base/models/tax.py:156
msgctxt "tax_code"
@@ -6276,10 +6264,8 @@ msgid "Reverse charge"
msgstr "Omgekeerde belastingheffing"
#: pretix/base/models/tax.py:168
#, fuzzy
#| msgid "Tax rate"
msgid "Tax free"
msgstr "Btw-tarief"
msgstr "Belastingvrij"
#: pretix/base/models/tax.py:171
msgctxt "tax_code"
@@ -6309,11 +6295,8 @@ msgstr ""
"diensten"
#: pretix/base/models/tax.py:187
#, fuzzy
#| msgctxt "cookie_usage"
#| msgid "Social features"
msgid "Special cases"
msgstr "Sociale functies"
msgstr "Uitzonderingen"
#: pretix/base/models/tax.py:189
msgctxt "tax_code"
@@ -6372,22 +6355,22 @@ msgstr ""
#: pretix/base/models/tax.py:254
msgctxt "tax_code"
msgid "Intra-Community acquisition from second hand means of transport"
msgstr ""
msgstr "Intracommunautaire aankoop van tweedehands transportmogelijkheden"
#: pretix/base/models/tax.py:256
msgctxt "tax_code"
msgid "Intra-Community acquisition of second hand goods"
msgstr ""
msgstr "Intracommunautaire aankoop van tweedehands goederen"
#: pretix/base/models/tax.py:258
msgctxt "tax_code"
msgid "Intra-Community acquisition of works of art"
msgstr ""
msgstr "Intracommunautaire aankoop van kunstwerken"
#: pretix/base/models/tax.py:260
msgctxt "tax_code"
msgid "Intra-Community acquisition of collectors items and antiques"
msgstr ""
msgstr "Intracommunautaire aankoop van verzamelobjecten en antiek"
#: pretix/base/models/tax.py:262
msgctxt "tax_code"
@@ -6415,10 +6398,8 @@ msgstr "Moet kort zijn, bijv. \"btw\""
#: pretix/base/models/tax.py:330 pretix/control/forms/event.py:1511
#: pretix/control/templates/pretixcontrol/order/transactions.html:22
#, fuzzy
#| msgid "Barcode"
msgid "Tax code"
msgstr "Barcode"
msgstr "Belastingtarief"
#: pretix/base/models/tax.py:331
msgid ""
@@ -7071,11 +7052,9 @@ msgid "The payment for this invoice has already been received."
msgstr "De betaling voor deze factuur is al ontvangen."
#: pretix/base/payment.py:970
#, fuzzy
#| msgid "This payment can not be canceled at the moment."
msgid ""
"This payment is already being processed and can not be canceled any more."
msgstr "Deze betaling kan momenteel niet worden geannuleerd."
msgstr "Deze betaling wordt al verwerkt en kan niet meer worden geannuleerd."
#: pretix/base/payment.py:984
msgid "Automatic refunds are not supported by this payment provider."
@@ -9701,10 +9680,8 @@ msgid "Automatically on user request"
msgstr "Automatisch op verzoek gebruiker"
#: pretix/base/settings.py:1043 pretix/base/settings.py:1056
#, fuzzy
#| msgid "Automatically on user request"
msgid "Automatically on user request for paid orders"
msgstr "Automatisch op verzoek gebruiker"
msgstr "Automatisch op verzoek van de gebruiker voor betaalde bestellingen"
#: pretix/base/settings.py:1044
msgid "Automatically for all created orders"
@@ -9897,10 +9874,8 @@ msgstr ""
"verschillende landen gesproken worden (zoals Engels)."
#: pretix/base/settings.py:1311
#, fuzzy
#| msgid "This is not an event series."
msgid "This shop represents an event"
msgstr "Dit is geen evenementenreeks."
msgstr "Deze shop hoort bij een evenement"
#: pretix/base/settings.py:1313
msgid ""
@@ -9910,6 +9885,12 @@ msgid ""
"page. Note that pretix still is a system built around events and the date "
"may still show up in other places."
msgstr ""
"Vink dit vakje uit als u alleen iets verkoopt dat geen specifieke datum "
"heeft, zoals cadeaubonnen of een ticket dat op elk moment gebruikt kan "
"worden. Het systeem zal de evenementdatum dan niet meer weergeven op sommige "
"plaatsen, zoals de startpagina van het evenement. Hou er evenwel rekening "
"mee dat pretix een systeem is dat voor evenementen is ontworpen en dat de "
"datum nog altijd op andere plaatsen kan verschijnen."
#: pretix/base/settings.py:1326
msgid "Show event end date"
@@ -12089,18 +12070,14 @@ msgid "MA"
msgstr "Msc."
#: pretix/base/settings.py:3720 pretix/base/settings.py:3722
#, fuzzy
#| msgid "Provider name"
msgctxt "address"
msgid "Province"
msgstr "Productnaam"
msgstr "Provincie"
#: pretix/base/settings.py:3721
#, fuzzy
#| msgid "Use feature"
msgctxt "address"
msgid "Prefecture"
msgstr "Gebruik functie"
msgstr "Prefectuur"
#: pretix/base/settings.py:3810 pretix/control/forms/event.py:228
msgid ""
@@ -12530,17 +12507,17 @@ msgstr "Foto uploaden"
#: pretix/base/templates/pretixbase/forms/widgets/reldate.html:14
#, python-format
msgid "%(number)s days %(relation)s %(relation_to)s"
msgstr ""
msgstr "%(number)s dagen %(relation)s %(relation_to)s"
#: pretix/base/templates/pretixbase/forms/widgets/reldatetime.html:14
#, python-format
msgid "%(number)s minutes %(relation)s %(relation_to)s"
msgstr ""
msgstr "%(number)s minuten %(relation)s %(relation_to)s"
#: pretix/base/templates/pretixbase/forms/widgets/reldatetime.html:18
#, python-format
msgid "%(number)s days %(relation)s %(relation_to)s at %(time_of_day)s"
msgstr ""
msgstr "%(number)s dagen %(relation)s %(relation_to)s om %(time_of_day)s"
#: pretix/base/templates/pretixbase/redirect.html:5
#: pretix/base/templates/pretixbase/redirect.html:9
@@ -13052,7 +13029,7 @@ msgstr "Je kan altijd later belastingregels configureren."
#: pretix/control/forms/event.py:148
msgid "Sales tax rate"
msgstr "Btw-tarief"
msgstr "Belastingtarief"
#: pretix/control/forms/event.py:149
msgid ""
@@ -13121,29 +13098,19 @@ msgstr "Standaard ({value})"
#: pretix/control/forms/event.py:384 pretix/control/forms/event.py:397
msgid "Domain"
msgstr ""
msgstr "Domein"
#: pretix/control/forms/event.py:388
#, fuzzy
#| msgid ""
#| "You can set up possible filters as meta properties in your organizer "
#| "settings."
msgid "You can configure this in your organizer settings."
msgstr ""
"U kunt de mogelijke filters als meta-eigenschappen instellen in uw "
"organisatorinstellingen."
msgstr "U kunt dit configureren in uw organisatorinstellingen."
#: pretix/control/forms/event.py:398
#, fuzzy
#| msgid "You can now login using your new password."
msgid "You can add more domains in your organizer account."
msgstr "U kunt nu inloggen met uw nieuwe wachtwoord."
msgstr "U kunt meer domains toevoegen in uw organisatoraccount."
#: pretix/control/forms/event.py:399
#, fuzzy
#| msgid "Organizer account"
msgid "Same as organizer account"
msgstr "Organisatoraccount"
msgstr "Zelfde als organisatoraccount"
#: pretix/control/forms/event.py:503
#, python-brace-format
@@ -13532,10 +13499,8 @@ msgid "Order requires approval"
msgstr "Bestelling vereist goedkeuring"
#: pretix/control/forms/event.py:1512
#, fuzzy
#| msgid "Default price"
msgid "Default tax code"
msgstr "Standaardprijs"
msgstr "Standaard belastingstarief"
#: pretix/control/forms/event.py:1516
msgid "Deviating tax rate"
@@ -13552,12 +13517,9 @@ msgid ""
msgstr ""
#: pretix/control/forms/event.py:1550 pretix/control/forms/event.py:1554
#, fuzzy
#| msgid "This combination of credentials is not known to our system."
msgid "This combination of calculation mode and tax code does not make sense."
msgstr ""
"Deze combinatie van gebruikersnaam en wachtwoord is niet bekend in onze "
"database."
"Deze combinatie van berekeningsmethode en belastingstarief is niet zinvol."
#: pretix/control/forms/event.py:1619
msgid "Pre-selected voucher"
@@ -14696,6 +14658,9 @@ msgid ""
"only use characters A-Z, a-z, 0-9, and common special characters "
"({characters})."
msgstr ""
"Het wachtwoord bevat tekens die niet worden ondersteund door ons e-"
"mailsysteem. Gebruik alleen de tekens A-Z, a-z, 0-9 en algemene speciale "
"tekens ({characters})."
#: pretix/control/forms/mailsetup.py:70
msgid "Use STARTTLS"
@@ -15010,6 +14975,9 @@ msgid ""
"Note that payment fees have a special semantic and might automatically be "
"changed if the payment method of the order is changed."
msgstr ""
"Hou er rekening mee dat betalingskosten een speciale semantiek hebben en "
"automatisch kunnen worden gewijzigd als de betalingsmethode van de "
"bestelling wordt gewijzigd."
#: pretix/control/forms/orders.py:628
#: pretix/control/templates/pretixcontrol/order/change.html:214
@@ -15055,10 +15023,9 @@ msgid "Recipient"
msgstr "Ontvanger"
#: pretix/control/forms/orders.py:768
#, fuzzy, python-brace-format
#| msgid "Attach ticket files"
#, python-brace-format
msgid "Attach {file}"
msgstr "Ticketbestanden bijvoegen bij e-mails"
msgstr "{file} toevoegen"
#: pretix/control/forms/orders.py:796
msgid ""
@@ -15268,27 +15235,24 @@ msgstr ""
"Dit domein is al in gebruik voor een ander evenement of andere organisator."
#: pretix/control/forms/organizer.py:185
#, fuzzy
#| msgid "You need to choose a subevent for the new position."
msgid "Do not choose an event for this mode."
msgstr "U moet een subevenement kiezen voor het nieuwe ticket."
msgstr "Hit is niet mogelijk een evenement te kiezen in deze modus."
#: pretix/control/forms/organizer.py:190
msgid ""
"Do not choose an event for this mode. You can assign events to this domain "
"in event settings."
msgstr ""
"Hit is niet mogelijk een evenement te kiezen in deze modus. U kan "
"evenementen toewijzen aan dit domein in de evenementinstellingen."
#: pretix/control/forms/organizer.py:195
#, fuzzy
#| msgctxt "subevent"
#| msgid "You need to select a date."
msgid "You need to choose an event."
msgstr "U moet een datum selecteren."
msgstr "U moet een evenement kiezen."
#: pretix/control/forms/organizer.py:227
msgid "You may set only one organizer domain."
msgstr ""
msgstr "Er kan maximaal 1 organisatordomein gekozen worden."
#: pretix/control/forms/organizer.py:334
msgid ""
@@ -15406,7 +15370,7 @@ msgstr "Telefoonnummerveld"
#: pretix/control/forms/organizer.py:1047
msgctxt "sso_oidc"
msgid "Query parameters"
msgstr ""
msgstr "Filterparameters"
#: pretix/control/forms/organizer.py:1048
#, python-brace-format
@@ -15872,10 +15836,7 @@ msgstr ""
"\"."
#: pretix/control/logdisplay.py:315
#, fuzzy, python-brace-format
#| msgid ""
#| "Scan scan of revoked code \"{barcode}…\" at {datetime} for list \"{list}"
#| "\", type \"{type}\", was uploaded."
#, python-brace-format
msgid ""
"Scan of revoked code \"{barcode}…\" at {datetime} for list \"{list}\", type "
"\"{type}\", was uploaded."
@@ -16860,28 +16821,22 @@ msgid "The check-in list has been changed."
msgstr "De inchecklijst is aangepast."
#: pretix/control/logdisplay.py:768
#, fuzzy, python-brace-format
#| msgid "Check-in list"
#, python-brace-format
msgid "Check-in list {val}"
msgstr "Inchecklijst"
msgstr "Inchecklijst {val}"
#: pretix/control/logdisplay.py:775
#, fuzzy
#| msgid "A plugin has been enabled."
msgid "The plugin has been enabled."
msgstr "Een plug-in is ingeschakeld."
msgstr "De plug-in is ingeschakeld."
#: pretix/control/logdisplay.py:776 pretix/control/views/event.py:461
#, fuzzy
#| msgid "A plugin has been disabled."
msgid "The plugin has been disabled."
msgstr "Een plug-in is uitgeschakeld."
msgstr "De plug-in is uitgeschakeld."
#: pretix/control/logdisplay.py:779
#, fuzzy, python-brace-format
#| msgid "Question {val}"
#, python-brace-format
msgid "Plugin {val}"
msgstr "Vraag {val}"
msgstr "Plugin {val}"
#: pretix/control/logdisplay.py:795
msgid "The product has been created."
@@ -17847,13 +17802,7 @@ msgid "Delete check-ins"
msgstr "Verwijder check-ins"
#: pretix/control/templates/pretixcontrol/checkin/bulk_revert_confirm.html:15
#, fuzzy, python-format
#| msgid ""
#| "Are you sure you want to permanently delete the check-ins of <strong>one "
#| "ticket</strong>."
#| msgid_plural ""
#| "Are you sure you want to permanently delete the check-ins of "
#| "<strong>%(count)s tickets</strong>?"
#, python-format
msgid ""
"Are you sure you want to permanently delete the check-ins of <strong>one "
"ticket</strong>?"
@@ -19395,10 +19344,8 @@ msgid "Disabled"
msgstr "Uitgeschakeld"
#: pretix/control/templates/pretixcontrol/event/payment.html:57
#, fuzzy
#| msgid "Enable waiting list"
msgid "Enable additional payment plugins"
msgstr "Wachtlijst inschakelen"
msgstr "Extra betaalplugins inschakelen"
#: pretix/control/templates/pretixcontrol/event/payment.html:66
msgid "Deadlines"
@@ -19498,10 +19445,8 @@ msgid "Your changes have been saved."
msgstr "Uw wijzigingen zijn opgeslagen."
#: pretix/control/templates/pretixcontrol/event/plugins.html:34
#, fuzzy
#| msgid "Check results"
msgid "Search results"
msgstr "Controleer resultaat"
msgstr "Zoekresultaten"
#: pretix/control/templates/pretixcontrol/event/plugins.html:56
msgid "Top recommendation"
@@ -19521,16 +19466,12 @@ msgstr "Niet beschikbaar"
#: pretix/control/templates/pretixcontrol/event/plugins.html:93
#: pretix/control/templates/pretixcontrol/event/plugins.html:105
#, fuzzy
#| msgid "Login settings"
msgid "Open plugin settings"
msgstr "Aanmeldinstellingen"
msgstr "Open plugin-instellingen"
#: pretix/control/templates/pretixcontrol/event/plugins.html:94
#, fuzzy
#| msgid "Go to shop"
msgid "Go to"
msgstr "Ga naar de winkel"
msgstr "Ga naar"
#: pretix/control/templates/pretixcontrol/event/plugins.html:116
#: pretix/control/templates/pretixcontrol/oauth/app_delete.html:15
@@ -19958,23 +19899,16 @@ msgstr ""
"ingesteld."
#: pretix/control/templates/pretixcontrol/event/tax_edit.html:58
#, fuzzy
#| msgctxt "discount"
#| msgid "Condition"
msgid "Condition"
msgstr "Voorwaarde"
#: pretix/control/templates/pretixcontrol/event/tax_edit.html:61
#, fuzzy
#| msgid "Cancellation"
msgid "Calculation"
msgstr "Annulering"
msgstr "Berekening"
#: pretix/control/templates/pretixcontrol/event/tax_edit.html:64
#, fuzzy
#| msgid "Reason:"
msgid "Reason"
msgstr "Reden:"
msgstr "Reden"
#: pretix/control/templates/pretixcontrol/event/tax_edit.html:137
#: pretix/control/templates/pretixcontrol/subevents/bulk.html:251
@@ -22390,9 +22324,6 @@ msgid "Subject:"
msgstr "Onderwerp:"
#: pretix/control/templates/pretixcontrol/order/mail_history.html:59
#, fuzzy
#| msgctxt "attachment_filename"
#| msgid "Calendar invite"
msgid "Calendar invite"
msgstr "Agenda-uitnodiging"
@@ -23797,28 +23728,24 @@ msgstr ""
"vereist dat alle chips vóór het eerste gebruik worden gecodeerd."
#: pretix/control/templates/pretixcontrol/organizers/edit.html:299
#, fuzzy
#| msgid "Known domains"
msgid "Domains"
msgstr "Bekende domeinen"
msgstr "Domeinen"
#: pretix/control/templates/pretixcontrol/organizers/edit.html:301
#, fuzzy
#| msgid "This action is only allowed for canceled orders."
msgid "This dialog is intended for advanced users."
msgstr "Deze actie is alleen toegestaan voor geannuleerde bestellingen."
msgstr "Deze dialoog is bedoeld voor gevorderde gebruikers."
#: pretix/control/templates/pretixcontrol/organizers/edit.html:302
msgid ""
"The domain needs to be configured on your webserver before it can be used "
"here."
msgstr ""
"Het domein moet worden geconfigureerd op uw eigen webserver voordat het hier "
"kan worden gebruikt."
#: pretix/control/templates/pretixcontrol/organizers/edit.html:358
#, fuzzy
#| msgid "Add link"
msgid "Add domain"
msgstr "Link toevoegen"
msgstr "Domein toevoegen"
#: pretix/control/templates/pretixcontrol/organizers/export.html:64
msgid "Run export now and download result"
@@ -24663,10 +24590,8 @@ msgid "Size (mm)"
msgstr "Grootte (mm)"
#: pretix/control/templates/pretixcontrol/pdf/index.html:327
#, fuzzy
#| msgid "Text color"
msgid "QR color"
msgstr "Tekstkleur"
msgstr "QR-kleur"
#: pretix/control/templates/pretixcontrol/pdf/index.html:342
msgid "Render without whitespace"
@@ -26430,13 +26355,11 @@ msgstr "API-functies"
#: pretix/control/views/event.py:444
msgid "The plugin {} is now active, you can configure it here:"
msgstr ""
msgstr "De plugin {} is nu geactiveerd, u kunt hem hier configureren:"
#: pretix/control/views/event.py:453
#, fuzzy
#| msgid "The selected ticket shop is currently not available."
msgid "The plugin {} is now active."
msgstr "De geselecteerde ticketwinkel is op dit moment niet beschikbaar."
msgstr "De plugin {} is nu geactiveerd."
#: pretix/control/views/event.py:516
msgid ""
@@ -26920,12 +26843,8 @@ msgid "Access for the selected application has been revoked."
msgstr "De toegang voor de gekozen applicatie is ingetrokken."
#: pretix/control/views/orders.py:192
#, fuzzy
#| msgid "We could not save your changes. See below for details."
msgid "We could not process your input. See below for details."
msgstr ""
"De wijzigingen konden niet worden opgeslagen, zie hieronder voor meer "
"informatie."
msgstr "Uw input kon niet worden verwerkt; zie hieronder voor meer informatie."
#: pretix/control/views/orders.py:265
#, python-brace-format
@@ -27999,32 +27918,24 @@ msgid "Unknown country"
msgstr "Onbekend land"
#: pretix/multidomain/models.py:36
#, fuzzy
#| msgid "Organizer name"
msgid "Organizer domain"
msgstr "Naam van de organisator"
msgstr "Domein van de organisator"
#: pretix/multidomain/models.py:37
#, fuzzy
#| msgid "Event organizer info text"
msgid "Alternative organizer domain for a set of events"
msgstr "Informatie over de organisator van het evenement"
msgstr "Alternatieve organisator voor een reeks evenementen"
#: pretix/multidomain/models.py:38
#, fuzzy
#| msgid "Event location"
msgid "Event domain"
msgstr "Evenementlocatie"
msgstr "Evenementdomain"
#: pretix/multidomain/models.py:44
#, fuzzy
#| msgid "Company name"
msgid "Domain name"
msgstr "Bedrijfsnaam"
msgstr "Domeinnaam"
#: pretix/multidomain/models.py:50
msgid "Mode"
msgstr ""
msgstr "Modus"
#: pretix/multidomain/models.py:69
msgid "Known domain"
@@ -30609,10 +30520,9 @@ msgid "An email rule was deleted"
msgstr "De e-mailregel is verwijderd"
#: pretix/plugins/sendmail/signals.py:140
#, fuzzy, python-brace-format
#| msgid "Tax rule {val}"
#, python-brace-format
msgid "Mail rule {val}"
msgstr "Belastingregel {val}"
msgstr "Mailregel {val}"
#: pretix/plugins/sendmail/templates/pretixplugins/sendmail/history.html:8
msgid ""
@@ -31318,7 +31228,7 @@ msgstr "Creditcard"
#: pretix/plugins/stripe/payment.py:1186
#, python-brace-format
msgid "expires {month}/{year}"
msgstr ""
msgstr "vervalt {month}/{year}"
#: pretix/plugins/stripe/payment.py:1191
msgid "SEPA Debit via Stripe"
@@ -31973,10 +31883,8 @@ msgstr ""
"maar vereist een moderne browser en een redelijke internetverbinding."
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:14
#, fuzzy
#| msgid "Open Layout Designer"
msgid "Open layout editor"
msgstr "Open layout-designer"
msgstr "Open de layout-editor"
#: pretix/plugins/ticketoutputpdf/templates/pretixplugins/ticketoutputpdf/form.html:18
msgid "Advanced mode (multiple layouts)"
@@ -32459,17 +32367,13 @@ msgstr ""
"kiezen voor u doorgaat."
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:16
#, fuzzy
#| 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."
msgid ""
"A product in your cart is only sold in combination with add-on products that "
"are not available. Please contact the event organizer."
msgstr ""
"Een product in uw winkelwagen wordt alleen verkocht in combinatie met "
"aanvullende producten die niet meer verkrijgbaar zijn. Neem contact op met "
"de organisator."
"aanvullende producten die niet verkrijgbaar zijn. Neem contact op met de "
"organisator."
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:20
msgid "We're now trying to book these add-ons for you!"
@@ -33113,7 +33017,7 @@ msgstr ""
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:341
#, python-format
msgid "%(percent)s %% Discount"
msgstr ""
msgstr "%(percent)s %% Korting"
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:272
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:345
@@ -34384,12 +34288,11 @@ msgid "Calendar"
msgstr "Kalender"
#: pretix/presale/templates/pretixpresale/fragment_calendar.html:29
#, fuzzy, python-format
#| msgid "%(count)s elements"
#, python-format
msgid "%(count)s event"
msgid_plural "%(count)s events"
msgstr[0] "%(count)s elementen"
msgstr[1] "%(count)s elementen"
msgstr[0] "%(count)s evenement"
msgstr[1] "%(count)s evenementen"
#: pretix/presale/templates/pretixpresale/fragment_calendar.html:68
#: pretix/presale/templates/pretixpresale/fragment_day_calendar.html:65
@@ -34637,10 +34540,8 @@ msgid "Addresses"
msgstr "Adressen"
#: pretix/presale/templates/pretixpresale/organizers/customer_addresses.html:37
#, fuzzy
#| msgid "No addresses are stored in your account."
msgid "You dont have any addresses in your account yet."
msgstr "Er zijn geen adressen opgeslagen in uw account."
msgstr "Er zijn nog geen adressen opgeslagen in uw account."
#: pretix/presale/templates/pretixpresale/organizers/customer_base.html:7
#: pretix/presale/templates/pretixpresale/organizers/customer_orders.html:7
@@ -34656,10 +34557,8 @@ msgid "Change password"
msgstr "Wachtwoord veranderen"
#: pretix/presale/templates/pretixpresale/organizers/customer_base.html:41
#, fuzzy
#| msgid "Customer account registration"
msgid "customer account information"
msgstr "Klantenaccount-registratie"
msgstr "klantenaccount-informatie"
#: pretix/presale/templates/pretixpresale/organizers/customer_info.html:6
msgid "Account information"
@@ -34685,48 +34584,35 @@ msgid "Your membership"
msgstr "Uw lidmaatschap"
#: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:40
#, fuzzy
#| msgid "Transfer"
msgid "transferable"
msgstr "Overdragen"
msgstr "overdraagbaar"
#: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:42
#, fuzzy
#| msgid "not answered"
msgid "not transferable"
msgstr "niet beantwoord"
msgstr "niet overdraagbaar"
#: pretix/presale/templates/pretixpresale/organizers/customer_membership.html:122
#, fuzzy
#| msgid "You haven't scanned any tickets yet."
msgid "You havent used this membership yet."
msgstr "U heeft nog geen tickets gescand."
msgstr "U heeft dit lidmaatschap nog niet gebruikt."
#: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:49
#, fuzzy
#| msgid "Expired"
msgid "Expired since"
msgstr "Verlopen"
msgstr "Verlopen sinds"
#: pretix/presale/templates/pretixpresale/organizers/customer_memberships.html:106
#, fuzzy
#| msgid "No memberships are stored in your account."
msgid "You dont have any memberships in your account yet."
msgstr "Er zijn geen lidmaatschappen gekoppeld aan uw account."
msgstr "Er zijn nog geen lidmaatschappen gekoppeld aan uw account."
#: pretix/presale/templates/pretixpresale/organizers/customer_orders.html:52
#, fuzzy, python-format
#| msgid "+ %(count)s invited"
#, python-format
msgid "%(counter)s item"
msgid_plural "%(counter)s items"
msgstr[0] "+ %(count)s uitgenodigd"
msgstr[1] "+ %(count)s uitgenodigd"
msgstr[0] "%(counter)s item"
msgstr[1] "%(counter)s items"
#: pretix/presale/templates/pretixpresale/organizers/customer_orders.html:78
#, fuzzy
#| msgid "You do not have permission to clone this event."
msgid "You dont have any orders in your account yet."
msgstr "U heeft geen toestemming om dit evenement te kopiëren."
msgstr "U heeft nog geen bestellingen in uw account."
#: pretix/presale/templates/pretixpresale/organizers/customer_password.html:6
#: pretix/presale/templates/pretixpresale/organizers/customer_resetpw.html:6
@@ -34756,10 +34642,8 @@ msgid "Attendee profiles"
msgstr "Gastenprofielen"
#: pretix/presale/templates/pretixpresale/organizers/customer_profiles.html:37
#, fuzzy
#| msgid "No attendee profiles are stored in your account."
msgid "You dont have any attendee profiles in your account yet."
msgstr "Er zijn geen profielen in uw account opgeslagen."
msgstr "Er zijn nog geen bezoekersprofielen in uw account opgeslagen."
#: pretix/presale/templates/pretixpresale/organizers/customer_registration.html:6
msgid "Registration"
@@ -34856,7 +34740,7 @@ msgstr ""
#: pretix/presale/views/cart.py:460 pretix/presale/views/cart.py:468
msgid ""
"The gift card has been saved to your cart. Please continue your checkout."
msgstr ""
msgstr "De cadeaubon is opgeslagen in uw winkelmandje. Ga verder met afrekenen."
#: pretix/presale/views/cart.py:504
msgid "Your cart has been updated."
@@ -34881,6 +34765,8 @@ msgid ""
"The gift card has been saved to your cart. Please now select the products "
"you want to purchase."
msgstr ""
"De cadeaubon is opgeslagen in uw winkelmandje. Selecteer nu de producten die "
"u wil kopen."
#: pretix/presale/views/cart.py:739
msgctxt "subevent"
@@ -35083,17 +34969,14 @@ msgstr ""
"omdat er geen betalingen meer geaccepteerd worden voor dit evenement."
#: pretix/presale/views/order.py:1646
#, fuzzy
#| msgid ""
#| "You may not change your order in a way that increases the total price "
#| "since payments are no longer being accepted for this event."
msgid ""
"You may not change your order in a way that requires additional payment "
"while we are processing your current payment. Please check back after your "
"current payment has been accepted."
msgstr ""
"U kunt de bestelling niet aanpassen dat de totaalprijs in verhoging brengt "
"omdat er geen betalingen meer geaccepteerd worden voor dit evenement."
"U kunt uw bestelling niet wijzigen op een manier die aanvullende betaling "
"vereist terwijl we uw huidige betaling aan het verwerken zijn. Probeer het "
"opnieuw nadat uw huidige betaling is geaccepteerd."
#: pretix/presale/views/order.py:1662 pretix/presale/views/order.py:1693
msgid "You cannot change this order."

View File

@@ -7,8 +7,8 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-25 15:46+0000\n"
"PO-Revision-Date: 2025-03-02 12:55+0000\n"
"Last-Translator: Tim Maurizio Dullaart <Tim.maurizio@gmail.com>\n"
"PO-Revision-Date: 2025-03-30 16:00+0000\n"
"Last-Translator: Jan Van Haver <jan.van.haver@gmail.com>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
"nl/>\n"
"Language: nl\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.10.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
@@ -685,10 +685,8 @@ msgid "Calculating default price…"
msgstr "Standaardprijs berekenen…"
#: pretix/static/pretixcontrol/js/ui/plugins.js:69
#, fuzzy
#| msgid "Search results"
msgid "No results"
msgstr "Zoekresultaten"
msgstr "Geen resultaten"
#: pretix/static/pretixcontrol/js/ui/question.js:42
msgid "Others"

View File

@@ -84,4 +84,12 @@
<dd>{{ payment_info.message }}</dd>
{% endif %}
</dl>
{% if payment_info.latest_charge.receipt_url %}
<p>
<a href="{{ payment_info.latest_charge.receipt_url }}" target="_blank">
<span class="fa fa-file-text"></span> {% trans "Payment receipt" %}
</a>
</p>
{% endif %}
{% endif %}

View File

@@ -23,10 +23,7 @@
{% trans "Seat" %}
</label>
<div class="col-md-9 form-control-text">
<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>
{% include "icons/seat.svg" with cls="svg-icon" %}
{{ form.position.seat }}
</div>
</div>

View File

@@ -100,10 +100,7 @@
{% trans "Seat" %}
</label>
<div class="col-md-9 form-control-text">
<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>
{% include "icons/seat.svg" with cls="svg-icon" %}
{{ pos.seat }}
</div>
</div>

View File

@@ -41,11 +41,8 @@
<div class="cart-icon-details">
<dt class="sr-only">{% trans "Seat:" %}</dt>
<dd>
<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 }}
{% include "icons/seat.svg" with cls="svg-icon" %}
{{ line.seat }}
</dd>
</div>
{% endif %}

View File

@@ -1,5 +1,6 @@
{% extends "pretixpresale/organizers/base.html" %}
{% load i18n %}
{% load date_fast %}
{% load icon %}
{% load rich_text %}
{% load tz %}
@@ -68,9 +69,10 @@
<br>
<span class="text-muted" data-time="{{ e.date_from.isoformat }}" data-timezone="{{ e.tzname }}">
{% icon "clock-o" %}
{{ e.date_from|date:"TIME_FORMAT" }}
<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 %}
{{ e.date_to|date:"TIME_FORMAT" }}
<span aria-hidden="true"></span><span class="sr-only">{% trans "until" context "timerange" %}</span>
<time datetime="{{ e.date_to|date_fast:"H:i" }}">{{ e.date_to|date:"TIME_FORMAT" }}</time>
{% endif %}
</span>
{% endtimezone %}

View File

@@ -479,7 +479,8 @@ class OrganizerIndex(OrganizerViewMixin, EventListMixin, ListView):
if event.has_subevents:
event.daterange = daterange(
event.min_from.astimezone(event.tzname),
(event.max_fromto or event.max_to or event.max_from).astimezone(event.tzname)
(event.max_fromto or event.max_to or event.max_from).astimezone(event.tzname),
as_html=True,
)
query_data = self.request.GET.copy()

View File

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

View File

@@ -922,7 +922,6 @@ var editor = {
$("#toolbox-heading").text(gettext("Ticket design"));
$("#pdf-info-width").val(editor._px2mm(editor.pdf_viewport.width).toFixed(2));
$("#pdf-info-height").val(editor._px2mm(editor.pdf_viewport.height).toFixed(2));
editor._paper_size_warning();
}
editor._update_toolbox_values();
},

View File

@@ -205,7 +205,11 @@ var form_handlers = function (el) {
return;
}
if ($timepicker.val() === "") {
date.set({'hour': 0, 'minute': 0, 'second': 0});
if (/_(until|end|to)(_|$)/.test($(this).attr("name"))) {
date.set({'hour': 23, 'minute': 59, 'second': 59});
} else {
date.set({'hour': 0, 'minute': 0, 'second': 0});
}
$timepicker.data('DateTimePicker').date(date);
}
});

View File

@@ -91,7 +91,11 @@ var form_handlers = function (el) {
return;
}
if ($timepicker.val() === "") {
date.set({'hour': 0, 'minute': 0, 'second': 0});
if (/_(until|end|to)(_|$)/.test($(this).attr("name"))) {
date.set({'hour': 23, 'minute': 59, 'second': 59});
} else {
date.set({'hour': 0, 'minute': 0, 'second': 0});
}
$timepicker.data('DateTimePicker').date(date);
}
});

View File

@@ -45,6 +45,7 @@ var strings = {
'loading_error_429': django.pgettext('widget', 'There are currently a lot of users in this ticket shop. Please ' +
'open the shop in a new tab to continue.'),
'open_new_tab': django.pgettext('widget', 'Open ticket shop'),
'checkout': django.pgettext('widget', 'Checkout'),
'cart_error': django.pgettext('widget', 'The cart could not be created. Please try again later'),
'cart_error_429': django.pgettext('widget', 'We could not create your cart, since there are currently too many ' +
'users in this ticket shop. Please click "Continue" to retry in a new tab.'),
@@ -77,6 +78,13 @@ var strings = {
'FR': django.gettext('Fr'),
'SA': django.gettext('Sa'),
'SU': django.gettext('Su'),
'MONDAY': django.gettext('Monday'),
'TUESDAY': django.gettext('Tuesday'),
'WEDNESDAY': django.gettext('Wednesday'),
'THURSDAY': django.gettext('Thursday'),
'FRIDAY': django.gettext('Friday'),
'SATURDAY': django.gettext('Saturday'),
'SUNDAY': django.gettext('Sunday'),
},
'months': {
'01': django.gettext('January'),
@@ -820,17 +828,18 @@ var shared_loading_fragment = (
);
var shared_iframe_fragment = (
'<div :class="frameClasses" role="dialog" aria-modal="true" >'
'<div :class="frameClasses" role="dialog" aria-modal="true" aria-label="'+strings.checkout+'">'
+ '<div class="pretix-widget-frame-loading" v-show="$root.frame_loading">'
+ '<svg width="256" height="256" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path class="pretix-widget-primary-color" d="M1152 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm512-109v222q0 12-8 23t-20 13l-185 28q-19 54-39 91 35 50 107 138 10 12 10 25t-9 23q-27 37-99 108t-94 71q-12 0-26-9l-138-108q-44 23-91 38-16 136-29 186-7 28-36 28h-222q-14 0-24.5-8.5t-11.5-21.5l-28-184q-49-16-90-37l-141 107q-10 9-25 9-14 0-25-11-126-114-165-168-7-10-7-23 0-12 8-23 15-21 51-66.5t54-70.5q-27-50-41-99l-183-27q-13-2-21-12.5t-8-23.5v-222q0-12 8-23t19-13l186-28q14-46 39-92-40-57-107-138-10-12-10-24 0-10 9-23 26-36 98.5-107.5t94.5-71.5q13 0 26 10l138 107q44-23 91-38 16-136 29-186 7-28 36-28h222q14 0 24.5 8.5t11.5 21.5l28 184q49 16 90 37l142-107q9-9 24-9 13 0 25 10 129 119 165 170 7 8 7 22 0 12-8 23-15 21-51 66.5t-54 70.5q26 50 41 98l183 28q13 2 21 12.5t8 23.5z"/></svg>'
+ '</div>'
+ '<div class="pretix-widget-frame-inner" ref="frame-container" v-show="$root.frame_shown">'
+ '<div class="pretix-widget-frame-close"><a href="#" @click.prevent.stop="close" role="button" aria-label="'+strings.close+'">'
+ '<svg height="16" viewBox="0 0 512 512" width="16" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5 c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9 c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/></svg>'
+ '<svg alt="'+strings.close+'" height="16" viewBox="0 0 512 512" width="16" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5 c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9 c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/></svg>'
+ '</a></div>'
+ '<iframe frameborder="0" width="650" height="650" @load="iframeLoaded" '
+ ' :name="$root.parent.widget_id" src="about:blank" v-once'
+ ' allow="autoplay *; camera *; fullscreen *; payment *"'
+ ' title="'+strings.checkout+'"'
+ ' referrerpolicy="origin">'
+ 'Please enable frames in your browser!'
+ '</iframe>'
@@ -862,7 +871,7 @@ var shared_lightbox_fragment = (
+ '<figcaption v-if="$root.lightbox.description">{{$root.lightbox.description}}</figcaption>'
+ '</figure>'
+ '<button type="button" class="pretix-widget-lightbox-close" @click="lightboxClose" aria-label="'+strings.close+'">'
+ '<svg height="16" viewBox="0 0 512 512" width="16" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5 c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9 c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/></svg>'
+ '<svg alt="'+strings.close+'" height="16" viewBox="0 0 512 512" width="16" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5 c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9 c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/></svg>'
+ '</button>'
+ '</div>'
+ '</div>'
@@ -964,10 +973,10 @@ Vue.component('pretix-widget-event-form', {
template: ('<div class="pretix-widget-event-form">'
// Back navigation
+ '<div class="pretix-widget-event-list-back" v-if="$root.events || $root.weeks || $root.days">'
+ '<a href="#" @click.prevent.stop="back_to_list" v-if="!$root.subevent">&lsaquo; '
+ '<a href="#" rel="back" @click.prevent.stop="back_to_list" v-if="!$root.subevent">&lsaquo; '
+ strings['back_to_list']
+ '</a>'
+ '<a href="#" @click.prevent.stop="back_to_list" v-if="$root.subevent">&lsaquo; '
+ '<a href="#" rel="back" @click.prevent.stop="back_to_list" v-if="$root.subevent">&lsaquo; '
+ strings['back_to_dates']
+ '</a>'
+ '</div>'
@@ -1119,6 +1128,11 @@ Vue.component('pretix-widget-event-form', {
back_to_list: function() {
this.$root.target_url = this.$root.parent_stack.pop();
this.$root.error = null;
if (!this.$root.subevent) {
// reset if we are not in a series
this.$root.name = null;
this.$root.frontpage_text = null;
}
this.$root.subevent = null;
this.$root.offset = 0;
this.$root.append_events = false;
@@ -1130,6 +1144,12 @@ Vue.component('pretix-widget-event-form', {
} else {
this.$root.view = "weeks";
}
var $el = this.$root.$el;
this.$root.$nextTick(function() {
// wait for redraw, then focus content element for better a11y
$el.focus();
});
},
calculate_buy_disabled: function() {
var i, j, k;
@@ -1197,7 +1217,7 @@ Vue.component('pretix-widget-event-list-filter-form', {
});
Vue.component('pretix-widget-event-list-entry', {
template: ('<a :class="classObject" @click.prevent.stop="select">'
template: ('<a href="#" :class="classObject" @click.prevent.stop="select">'
+ '<div class="pretix-widget-event-list-entry-name">{{ event.name }}</div>'
+ '<div class="pretix-widget-event-list-entry-date">{{ event.date_range }}</div>'
+ '<div class="pretix-widget-event-list-entry-location">{{ location }}</div>' // hidden by css for now, but
@@ -1237,7 +1257,7 @@ Vue.component('pretix-widget-event-list-entry', {
Vue.component('pretix-widget-event-list', {
template: ('<div class="pretix-widget-event-list">'
+ '<div class="pretix-widget-back" v-if="$root.weeks || $root.parent_stack.length > 0">'
+ '<a href="#" @click.prevent.stop="back_to_calendar" role="button">&lsaquo; '
+ '<a href="#" rel="prev" @click.prevent.stop="back_to_calendar">&lsaquo; '
+ strings['back']
+ '</a>'
+ '</div>'
@@ -1256,6 +1276,10 @@ Vue.component('pretix-widget-event-list', {
},
methods: {
back_to_calendar: function () {
// make sure to always focus content element
this.$nextTick(function () {
this.$root.$el.focus();
});
this.$root.offset = 0;
this.$root.append_events = false;
if (this.$root.weeks) {
@@ -1280,7 +1304,7 @@ Vue.component('pretix-widget-event-list', {
});
Vue.component('pretix-widget-event-calendar-event', {
template: ('<a :class="classObject" @click.prevent.stop="select">'
template: ('<a href="#" :class="classObject" @click.prevent.stop="select" v-bind:aria-describedby="describedby">'
+ '<strong class="pretix-widget-event-calendar-event-name">'
+ '{{ event.name }}'
+ '</strong>'
@@ -1288,7 +1312,8 @@ Vue.component('pretix-widget-event-calendar-event', {
+ '<div class="pretix-widget-event-calendar-event-availability" v-if="!event.continued && event.availability.text">{{ event.availability.text }}</div>'
+ '</a>'),
props: {
event: Object
event: Object,
describedby: String,
},
computed: {
classObject: function () {
@@ -1316,11 +1341,11 @@ Vue.component('pretix-widget-event-calendar-event', {
Vue.component('pretix-widget-event-week-cell', {
template: ('<div :class="classObject" @click.prevent.stop="selectDay">'
+ '<div class="pretix-widget-event-calendar-day" v-if="day">'
+ '<div class="pretix-widget-event-calendar-day" v-if="day" :id="id">'
+ '{{ dayhead }}'
+ '</div>'
+ '<div class="pretix-widget-event-calendar-events" v-if="day">'
+ '<pretix-widget-event-calendar-event v-for="e in day.events" :event="e"></pretix-widget-event-calendar-event>'
+ '<pretix-widget-event-calendar-event v-for="e in day.events" :event="e" :describedby="id"></pretix-widget-event-calendar-event>'
+ '</div>'
+ '</div>'),
props: {
@@ -1346,6 +1371,9 @@ Vue.component('pretix-widget-event-week-cell', {
}
},
computed: {
id: function () {
return this.day ? this.$root.html_id + '-' + this.day.date : '';
},
dayhead: function () {
if (!this.day) {
return;
@@ -1381,7 +1409,7 @@ Vue.component('pretix-widget-event-week-cell', {
Vue.component('pretix-widget-event-calendar-cell', {
template: ('<td :class="classObject" @click.prevent.stop="selectDay">'
+ '<div class="pretix-widget-event-calendar-day" v-if="day">'
+ '<div class="pretix-widget-event-calendar-day" v-if="day" v-bind:aria-label="date">'
+ '{{ daynum }}'
+ '</div>'
+ '<div class="pretix-widget-event-calendar-events" v-if="day">'
@@ -1417,6 +1445,9 @@ Vue.component('pretix-widget-event-calendar-cell', {
}
return this.day.date.substr(8);
},
date: function () {
return this.day ? (new Date(this.day.date)).toLocaleDateString() : '';
},
classObject: function () {
var o = {};
if (this.day && this.day.events.length > 0) {
@@ -1474,26 +1505,26 @@ Vue.component('pretix-widget-event-calendar', {
// Calendar navigation
+ '<div class="pretix-widget-event-calendar-head">'
+ '<a class="pretix-widget-event-calendar-previous-month" href="#" @click.prevent.stop="prevmonth" role="button">&laquo; '
+ '<a class="pretix-widget-event-calendar-previous-month" href="#" @click.prevent.stop="prevmonth">&laquo; '
+ strings['previous_month']
+ '</a> '
+ '<strong>{{ monthname }}</strong> '
+ '<a class="pretix-widget-event-calendar-next-month" href="#" @click.prevent.stop="nextmonth" role="button">'
+ '<a class="pretix-widget-event-calendar-next-month" href="#" @click.prevent.stop="nextmonth">'
+ strings['next_month']
+ ' &raquo;</a>'
+ '</div>'
// Calendar
+ '<table class="pretix-widget-event-calendar-table">'
+ '<table class="pretix-widget-event-calendar-table" :id="id" tabindex="0" v-bind:aria-label="monthname">'
+ '<thead>'
+ '<tr>'
+ '<th>' + strings['days']['MO'] + '</th>'
+ '<th>' + strings['days']['TU'] + '</th>'
+ '<th>' + strings['days']['WE'] + '</th>'
+ '<th>' + strings['days']['TH'] + '</th>'
+ '<th>' + strings['days']['FR'] + '</th>'
+ '<th>' + strings['days']['SA'] + '</th>'
+ '<th>' + strings['days']['SU'] + '</th>'
+ '<th aria-label="' + strings['days']['MONDAY'] + '">' + strings['days']['MO'] + '</th>'
+ '<th aria-label="' + strings['days']['TUESDAY'] + '">' + strings['days']['TU'] + '</th>'
+ '<th aria-label="' + strings['days']['WEDNESDAY'] + '">' + strings['days']['WE'] + '</th>'
+ '<th aria-label="' + strings['days']['THURSDAY'] + '">' + strings['days']['TH'] + '</th>'
+ '<th aria-label="' + strings['days']['FRIDAY'] + '">' + strings['days']['FR'] + '</th>'
+ '<th aria-label="' + strings['days']['SATURDAY'] + '">' + strings['days']['SA'] + '</th>'
+ '<th aria-label="' + strings['days']['SUNDAY'] + '">' + strings['days']['SU'] + '</th>'
+ '</tr>'
+ '</thead>'
+ '<tbody>'
@@ -1507,7 +1538,10 @@ Vue.component('pretix-widget-event-calendar', {
},
monthname: function () {
return strings['months'][this.$root.date.substr(5, 2)] + ' ' + this.$root.date.substr(0, 4);
}
},
id: function () {
return this.$root.html_id + "-event-calendar-table";
},
},
methods: {
back_to_list: function () {
@@ -1526,7 +1560,7 @@ Vue.component('pretix-widget-event-calendar', {
}
this.$root.date = String(curYear) + "-" + padNumber(curMonth, 2) + "-01";
this.$root.loading++;
this.$root.reload();
this.$root.reload({focus: '#'+this.id});
},
nextmonth: function () {
var curMonth = parseInt(this.$root.date.substr(5, 2));
@@ -1538,7 +1572,7 @@ Vue.component('pretix-widget-event-calendar', {
}
this.$root.date = String(curYear) + "-" + padNumber(curMonth, 2) + "-01";
this.$root.loading++;
this.$root.reload();
this.$root.reload({focus: '#'+this.id});
}
},
});
@@ -1573,7 +1607,7 @@ Vue.component('pretix-widget-event-week-calendar', {
+ '</div>'
// Actual calendar
+ '<div class="pretix-widget-event-week-table">'
+ '<div class="pretix-widget-event-week-table" :id="id" tabindex="0" v-bind:aria-label="weekname">'
+ '<div class="pretix-widget-event-week-col" v-for="d in $root.days">'
+ '<pretix-widget-event-week-cell :day="d">'
+ '</pretix-widget-event-week-cell>'
@@ -1591,6 +1625,9 @@ Vue.component('pretix-widget-event-week-calendar', {
var curYear = this.$root.week[0];
return curWeek + ' / ' + curYear;
},
id: function () {
return this.$root.html_id + "-event-week-table";
},
},
methods: {
back_to_list: function () {
@@ -1609,7 +1646,7 @@ Vue.component('pretix-widget-event-week-calendar', {
}
this.$root.week = [curYear, curWeek];
this.$root.loading++;
this.$root.reload();
this.$root.reload({focus: '#'+this.id});
},
nextweek: function () {
var curWeek = this.$root.week[1];
@@ -1621,13 +1658,13 @@ Vue.component('pretix-widget-event-week-calendar', {
}
this.$root.week = [curYear, curWeek];
this.$root.loading++;
this.$root.reload();
this.$root.reload({focus: '#'+this.id});
}
},
});
Vue.component('pretix-widget', {
template: ('<div class="pretix-widget-wrapper" ref="wrapper">'
template: ('<div class="pretix-widget-wrapper" ref="wrapper" tabindex="0" role="article" v-bind:aria-label="$root.name">'
+ '<div :class="classObject">'
+ shared_loading_fragment
+ '<div class="pretix-widget-error-message" v-if="$root.error && $root.view !== \'event\'">{{ $root.error }}</div>'
@@ -1737,7 +1774,7 @@ var shared_root_methods = {
}
});
},
reload: function () {
reload: function (opt = {}) {
var url;
if (this.$root.is_button) {
return;
@@ -1854,6 +1891,15 @@ var shared_root_methods = {
// If we're on desktop and someone selects a seating-only event in a calendar, let's open it right away,
// but only if the person didn't close it before.
root.startseating()
} else {
// make sure to only move focus to content element when it had focus before the reload/click
// this is needed because reload is also called on initial load and we do not want to move focus on initial load
if (root.$el.contains(document.activeElement)) {
root.$nextTick(function() {
// wait for redraw, then focus content element for better a11y
(opt.focus ? document.querySelector(opt.focus) : root.$el).focus();
});
}
}
}, function (error) {
root.categories = [];

View File

@@ -108,6 +108,7 @@ TEST_ORDERPOSITION1_RES = {
"order__status": "p",
"order__require_approval": False,
"order__valid_if_pending": False,
"order__locale": "en",
"order": "FOO",
"positionid": 1,
"item": 1,
@@ -146,6 +147,7 @@ TEST_ORDERPOSITION2_RES = {
"order__status": "p",
"order__require_approval": False,
"order__valid_if_pending": False,
"order__locale": "en",
"order": "FOO",
"positionid": 2,
"item": 1,
@@ -184,6 +186,7 @@ TEST_ORDERPOSITION3_RES = {
"order__status": "p",
"order__require_approval": False,
"order__valid_if_pending": False,
"order__locale": "en",
"order": "FOO",
"positionid": 3,
"item": 1,

View File

@@ -28,6 +28,7 @@ from django.core.files.base import ContentFile
from django.utils.timezone import now
from django_countries.fields import Country
from django_scopes import scopes_disabled
from freezegun import freeze_time
from i18nfield.strings import LazyI18nString
from tests.const import SAMPLE_PNG
@@ -148,6 +149,7 @@ TEST_ORDERPOSITION1_RES = {
"order__status": "p",
"order__require_approval": False,
"order__valid_if_pending": False,
"order__locale": "en",
"order": "FOO",
"positionid": 1,
"item": 1,
@@ -200,7 +202,7 @@ def clist_event2(event2):
return c
def _redeem(token_client, org, clist, p, body=None, query=''):
def _redeem(token_client, org, clist, p, body=None, query='', headers={}):
body = body or {}
if isinstance(clist, list):
body['lists'] = [c.pk for c in clist]
@@ -209,7 +211,7 @@ def _redeem(token_client, org, clist, p, body=None, query=''):
body['secret'] = p
return token_client.post('/api/v1/organizers/{}/checkinrpc/redeem/{}'.format(
org.slug, query,
), body, format='json')
), body, format='json', headers={})
@pytest.mark.django_db
@@ -1050,3 +1052,28 @@ def test_checkin_no_pdf_data(token_client, event, team, organizer, clist_all, or
resp = token_client.get(
'/api/v1/organizers/{}/checkinrpc/search/?list={}&search=dummy&pdf_data=true'.format(organizer.slug, clist_all.pk))
assert not resp.data['results'][0].get('pdf_data')
@pytest.mark.django_db
def test_reason_explanation_localization(token_client, organizer, clist, other_item, event, order):
event.settings.locales = ["de", "en"]
order.locale = "de"
order.save()
with scopes_disabled():
p = order.positions.first()
p.valid_from = datetime.datetime(2020, 1, 1, 12, 0, 0, tzinfo=event.timezone)
p.save()
with freeze_time("2020-01-01 10:45:00"):
resp = _redeem(token_client, organizer, clist, 'z3fsn8jyufm5kpk768q69gkbyr5f4h6w', {})
assert resp.status_code == 400
assert resp.data["status"] == "error"
assert resp.data["reason"] == "invalid_time"
assert resp.data["reason_explanation"] == "This ticket is only valid after 2020-01-01 12:00."
resp = _redeem(token_client, organizer, clist, 'z3fsn8jyufm5kpk768q69gkbyr5f4h6w', {
"use_order_locale": True
})
assert resp.status_code == 400
assert resp.data["status"] == "error"
assert resp.data["reason"] == "invalid_time"
assert resp.data["reason_explanation"] == "Erst ab 01.01.2020 12:00 gültig."

View File

@@ -47,6 +47,8 @@ TEST_DISCOUNT_RES = {
"available_from": None,
"available_until": None,
"subevent_mode": "mixed",
"subevent_date_from": None,
"subevent_date_until": None,
"condition_all_products": True,
"condition_limit_products": [],
"condition_apply_to_addons": True,

View File

@@ -2476,18 +2476,26 @@ class EventTest(TestCase):
datetime.datetime(2025, 3, 9, 21, 0, 0, tzinfo=tz),
datetime.datetime(2025, 3, 10, 3, 0, 0, tzinfo=tz),
'March 9th 10th, 2025',
'<time datetime="2025-03-09">March 9th</time> <time datetime="2025-03-10">10th, 2025</time>',
'<time datetime="2025-03-09">March 9th</time> '
'<span aria-hidden="true"></span><span class="sr-only"> until </span> '
'<time datetime="2025-03-10">10th, 2025</time>',
'March 9th 10th, 2025 20:0002:00',
'<time datetime="2025-03-09">March 9th</time> <time datetime="2025-03-10">10th, 2025</time> '
'<time datetime="2025-03-09">March 9th</time> '
'<span aria-hidden="true"></span><span class="sr-only"> until </span> '
'<time datetime="2025-03-10">10th, 2025</time> '
'<time datetime="2025-03-09T21:00:00+01:00" data-timezone="UTC" data-time-short>20:0002:00</time>'
),
(
datetime.datetime(2025, 3, 9, 21, 0, 0, tzinfo=tz),
datetime.datetime(2025, 3, 12, 14, 0, 0, tzinfo=tz),
'March 9th 12th, 2025',
'<time datetime="2025-03-09">March 9th</time> <time datetime="2025-03-12">12th, 2025</time>',
'<time datetime="2025-03-09">March 9th</time> '
'<span aria-hidden="true"></span><span class="sr-only"> until </span> '
'<time datetime="2025-03-12">12th, 2025</time>',
'March 9th 12th, 2025',
'<time datetime="2025-03-09">March 9th</time> <time datetime="2025-03-12">12th, 2025</time>',
'<time datetime="2025-03-09">March 9th</time> '
'<span aria-hidden="true"></span><span class="sr-only"> until </span> '
'<time datetime="2025-03-12">12th, 2025</time>',
),
(
datetime.datetime(2025, 3, 9, 21, 0, 0, tzinfo=tz),

View File

@@ -3243,6 +3243,18 @@ class OrderChangeManagerTests(TestCase):
assert nop.tax_rate == Decimal('0.00')
assert nop.tax_value == Decimal('0.00')
@classscope(attr='o')
def test_change_taxrate_and_keep_net(self):
self.ocm.change_tax_rule(self.op1, self.tr19)
self.ocm.recalculate_taxes(keep='net')
self.ocm.commit()
self.order.refresh_from_db()
nop = self.order.positions.first()
assert nop.price == Decimal('25.59')
assert nop.tax_rule == self.tr19
assert nop.tax_rate == Decimal('19.00')
assert nop.tax_value == Decimal('4.09')
@classscope(attr='o')
def test_change_taxrate_to_country_specific(self):
self.tr19.eu_reverse_charge = True

View File

@@ -142,7 +142,7 @@ testcases_single_rule = [
(
mixed_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 2,
(
Decimal('120.00'),
@@ -152,7 +152,7 @@ testcases_single_rule = [
(
mixed_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 3,
(
Decimal('96.00'),
@@ -163,12 +163,12 @@ testcases_single_rule = [
(
mixed_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -184,7 +184,7 @@ testcases_single_rule = [
(
mixed_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 2,
(
Decimal('120.00'),
@@ -194,7 +194,7 @@ testcases_single_rule = [
(
mixed_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 3,
(
Decimal('0.00'),
@@ -205,7 +205,7 @@ testcases_single_rule = [
(
mixed_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 5,
(
Decimal('0.00'),
@@ -218,7 +218,7 @@ testcases_single_rule = [
(
mixed_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 6,
(
Decimal('0.00'),
@@ -232,12 +232,12 @@ testcases_single_rule = [
(
mixed_min_count_one_free,
(
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('5.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('5.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('6.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -253,7 +253,7 @@ testcases_single_rule = [
(
mixed_min_value_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 4,
(
Decimal('120.00'),
@@ -265,7 +265,7 @@ testcases_single_rule = [
(
mixed_min_value_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 5,
(
Decimal('96.00'),
@@ -278,7 +278,7 @@ testcases_single_rule = [
(
mixed_min_value_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
) * 10,
(
Decimal('96.00'),
@@ -298,10 +298,10 @@ testcases_single_rule = [
(
same_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -313,11 +313,11 @@ testcases_single_rule = [
(
same_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -330,14 +330,14 @@ testcases_single_rule = [
(
same_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -355,15 +355,15 @@ testcases_single_rule = [
(
same_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -380,15 +380,15 @@ testcases_single_rule = [
(
same_min_count_one_free,
(
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('5.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('7.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('8.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('9.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('5.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('6.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('7.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('8.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('9.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -407,15 +407,15 @@ testcases_single_rule = [
(
same_min_value_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -434,9 +434,9 @@ testcases_single_rule = [
(
distinct_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -447,9 +447,9 @@ testcases_single_rule = [
(
distinct_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -460,14 +460,14 @@ testcases_single_rule = [
(
distinct_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -483,13 +483,13 @@ testcases_single_rule = [
(
distinct_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -504,13 +504,13 @@ testcases_single_rule = [
(
distinct_min_count_matching_percent,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('96.00'),
@@ -527,9 +527,9 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -540,9 +540,9 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -553,12 +553,12 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -572,12 +572,12 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('3.00'), False, False, Decimal('0.00')),
),
(
Decimal('3.00'),
@@ -591,12 +591,12 @@ testcases_single_rule = [
(
distinct_min_count_two_free,
(
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('3.00'), False, False, Decimal('0.00')),
),
(
Decimal('3.00'),
@@ -610,12 +610,12 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 5, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 6, Decimal('120.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 5, now(), Decimal('120.00'), False, False, Decimal('0.00')),
(1, 6, now(), Decimal('120.00'), False, False, Decimal('0.00')),
),
(
Decimal('120.00'),
@@ -629,12 +629,12 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('3.00'), False, False, Decimal('0.00')),
(1, 4, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 5, Decimal('5.00'), False, False, Decimal('0.00')),
(1, 6, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('3.00'), False, False, Decimal('0.00')),
(1, 4, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 5, now(), Decimal('5.00'), False, False, Decimal('0.00')),
(1, 6, now(), Decimal('6.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -648,12 +648,12 @@ testcases_single_rule = [
(
distinct_min_count_one_free,
(
(1, 1, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('4.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 2, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 3, Decimal('6.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('4.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('6.00'), False, False, Decimal('0.00')),
(1, 2, now(), Decimal('6.00'), False, False, Decimal('0.00')),
(1, 3, now(), Decimal('6.00'), False, False, Decimal('0.00')),
),
(
# This one is unexpected, since the customer could get a lower price
@@ -674,7 +674,7 @@ testcases_single_rule = [
Discount(condition_min_count=1, benefit_discount_matching_percent=20),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -689,8 +689,8 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('0.00'),
@@ -708,9 +708,9 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('100.00'),
@@ -728,9 +728,9 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -747,11 +747,11 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -770,9 +770,9 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
),
(
Decimal('100.00'),
@@ -791,9 +791,9 @@ testcases_single_rule = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, True, Decimal('0.00')),
(1, 1, Decimal('100.00'), True, True, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, True, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), True, True, Decimal('0.00')),
),
(
Decimal('100.00'),
@@ -818,9 +818,9 @@ testcases_multiple_rules = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -843,9 +843,9 @@ testcases_multiple_rules = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -867,9 +867,9 @@ testcases_multiple_rules = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('100.00'),
@@ -890,11 +890,11 @@ testcases_multiple_rules = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('100.00'),
@@ -917,9 +917,9 @@ testcases_multiple_rules = [
),
),
(
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
),
(
Decimal('80.00'),
@@ -954,10 +954,10 @@ def test_limit_products(event, item, item2):
d2.save()
positions = (
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('80.00'),
@@ -979,10 +979,10 @@ def test_limit_products_subevents_distinct(event, item, item2):
d1.condition_limit_products.add(item)
positions = (
(item.pk, 1, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, 2, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, 3, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, 4, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, 2, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, 3, now(), Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, 4, now(), Decimal('50.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('80.00'),
@@ -1007,8 +1007,8 @@ def test_sales_channels(event, item):
d2.limit_sales_channels.add(event.organizer.sales_channels.get(identifier="bar"))
positions = (
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'bar', positions)]) == [Decimal('80.00'), Decimal('80.00')]
@@ -1024,8 +1024,8 @@ def test_available_from(event, item):
d2.save()
positions = (
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
@@ -1040,13 +1040,78 @@ def test_available_until(event, item):
d2.save()
positions = (
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
@pytest.mark.django_db
@scopes_disabled()
def test_subevent_date_from(event, item, subevent):
subevent_date = subevent.date_from # prevent test timing errors
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
subevent_date_from=subevent_date + timedelta(days=1))
d1.save()
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
subevent_date_from=subevent_date)
d2.save()
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
positions = (
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
@pytest.mark.django_db
@scopes_disabled()
def test_subevent_date_until(event, item, subevent):
subevent_date = subevent.date_from # prevent test timing errors
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
subevent_date_until=subevent_date + timedelta(days=1))
d1.save()
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
subevent_date_until=subevent_date)
d2.save()
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
positions = (
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('80.00'), Decimal('80.00')]
@pytest.mark.django_db
@scopes_disabled()
def test_subevent_date_from_until(event, item, subevent):
subevent_date = subevent.date_from # prevent test timing errors
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
subevent_date_from=subevent_date + timedelta(days=1),
subevent_date_until=subevent_date + timedelta(days=2))
d1.save()
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
subevent_date_from=subevent_date - timedelta(days=2),
subevent_date_until=subevent_date - timedelta(days=1))
d2.save()
d3 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=80,
subevent_date_from=subevent_date, subevent_date_until=subevent_date + timedelta(days=1))
d3.save()
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
positions = (
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
)
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('20.00'), Decimal('20.00')]
@pytest.mark.django_db
@scopes_disabled()
def test_discount_other_products_min_count(event, item, item2):
@@ -1064,21 +1129,21 @@ def test_discount_other_products_min_count(event, item, item2):
d1.benefit_limit_products.add(item)
positions = (
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('100.00'),
@@ -1120,12 +1185,12 @@ def test_discount_other_products_min_count_no_addon(event, item, item2):
d1.benefit_limit_products.add(item)
positions = (
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), True, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), True, False, Decimal('0.00')),
)
expected = (
Decimal('100.00'),
@@ -1158,13 +1223,13 @@ def test_discount_other_products_min_count_no_voucher(event, item, item2):
d1.benefit_limit_products.add(item)
positions = (
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('40.00'), False, False, Decimal('50.00')),
(item.pk, None, Decimal('40.00'), False, False, Decimal('50.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('40.00'), False, False, Decimal('50.00')),
(item.pk, None, None, Decimal('40.00'), False, False, Decimal('50.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('100.00'),
@@ -1199,21 +1264,21 @@ def test_discount_subgroup_cheapest_n_min_count(event, item, item2):
positions = (
# 11 items of item2, which contribute to the total count of 15, but do not get reduced
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
# 4 items of item, of which 3 of the cheapest will be reduced
(item.pk, None, Decimal('110.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('110.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('110.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('110.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('100.00'),
@@ -1252,10 +1317,10 @@ def test_discount_other_products_min_value(event, item, item2):
d1.benefit_limit_products.add(item2)
positions = (
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('50.00'),
@@ -1268,11 +1333,11 @@ def test_discount_other_products_min_value(event, item, item2):
assert sorted(new_prices) == sorted(expected)
positions = (
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
)
expected = (
Decimal('50.00'),
@@ -1316,16 +1381,16 @@ def test_multiple_discounts_with_benefit_condition_overlap(event, item, item2):
d2.condition_limit_products.add(item)
positions = (
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
)
expected = (
# item2 remains untouched
@@ -1379,16 +1444,16 @@ def test_multiple_discounts_with_same_condition(event, item, item2, item3):
d2.benefit_limit_products.add(item3)
positions = (
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
)
expected = (
# both item1 remain full price

View File

@@ -73,7 +73,9 @@ def test_same_month_german():
df = date(2003, 2, 1)
dt = date(2003, 2, 3)
assert daterange(df, dt) == "1.3. Februar 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1.</time><time datetime="2003-02-03">3. Februar 2003</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1.</time>' \
'<span aria-hidden="true"></span><span class="sr-only"> bis </span>' \
'<time datetime="2003-02-03">3. Februar 2003</time>'
def test_same_month_english():
@@ -81,15 +83,19 @@ def test_same_month_english():
df = date(2003, 2, 1)
dt = date(2003, 2, 3)
assert daterange(df, dt) == "Feb. 1st 3rd, 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1st</time> <time datetime="2003-02-03">3rd, 2003</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1st</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2003-02-03">3rd, 2003</time>'
def test_same_month_spanish():
with translation.override('es'):
df = date(2003, 2, 1)
dt = date(2003, 2, 3)
assert daterange(df, dt) == "1 - 3 de febrero de 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1</time> - <time datetime="2003-02-03">3 de febrero de 2003</time>'
assert daterange(df, dt) == "1 3 de febrero de 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> hasta </span> ' \
'<time datetime="2003-02-03">3 de febrero de 2003</time>'
def test_same_year_german():
@@ -97,7 +103,9 @@ def test_same_year_german():
df = date(2003, 2, 1)
dt = date(2003, 4, 3)
assert daterange(df, dt) == "1. Februar 3. April 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1. Februar</time> <time datetime="2003-04-03">3. April 2003</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1. Februar</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> bis </span> ' \
'<time datetime="2003-04-03">3. April 2003</time>'
def test_same_year_english():
@@ -105,15 +113,19 @@ def test_same_year_english():
df = date(2003, 2, 1)
dt = date(2003, 4, 3)
assert daterange(df, dt) == "Feb. 1st April 3rd, 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1st</time> <time datetime="2003-04-03">April 3rd, 2003</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1st</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2003-04-03">April 3rd, 2003</time>'
def test_same_year_spanish():
with translation.override('es'):
df = date(2003, 2, 1)
dt = date(2003, 4, 3)
assert daterange(df, dt) == "1 de febrero - 3 de abril de 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1 de febrero</time> - <time datetime="2003-04-03">3 de abril de 2003</time>'
assert daterange(df, dt) == "1 de febrero 3 de abril de 2003"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1 de febrero</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> hasta </span> ' \
'<time datetime="2003-04-03">3 de abril de 2003</time>'
def test_different_dates_german():
@@ -121,7 +133,9 @@ def test_different_dates_german():
df = date(2003, 2, 1)
dt = date(2005, 4, 3)
assert daterange(df, dt) == "1. Februar 2003 3. April 2005"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1. Februar 2003</time> <time datetime="2005-04-03">3. April 2005</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1. Februar 2003</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> bis </span> ' \
'<time datetime="2005-04-03">3. April 2005</time>'
def test_different_dates_english():
@@ -129,7 +143,9 @@ def test_different_dates_english():
df = date(2003, 2, 1)
dt = date(2005, 4, 3)
assert daterange(df, dt) == "Feb. 1, 2003 April 3, 2005"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1, 2003</time> <time datetime="2005-04-03">April 3, 2005</time>'
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">Feb. 1, 2003</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2005-04-03">April 3, 2005</time>'
def test_different_dates_spanish():
@@ -137,7 +153,8 @@ def test_different_dates_spanish():
df = date(2003, 2, 1)
dt = date(2005, 4, 3)
assert daterange(df, dt) == "1 de febrero de 2003 3 de abril de 2005"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1 de febrero de 2003</time> ' \
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">1 de febrero de 2003</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> hasta </span> ' \
'<time datetime="2005-04-03">3 de abril de 2005</time>'
@@ -146,7 +163,8 @@ def test_different_dates_other_lang():
df = date(2003, 2, 1)
dt = date(2005, 4, 3)
assert daterange(df, dt) == "01 Şubat 2003 03 Nisan 2005"
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">01 Şubat 2003</time> ' \
assert daterange(df, dt, as_html=True) == '<time datetime="2003-02-01">01 Şubat 2003</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2005-04-03">03 Nisan 2005</time>'
@@ -155,13 +173,15 @@ def test_datetime_same_day():
df = datetime(2003, 2, 1, 9, 0)
dt = datetime(2003, 2, 1, 10, 0)
assert datetimerange(df, dt) == "01.02.2003 09:00 10:00"
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">01.02.2003 09:00</time> ' \
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">01.02.2003 09:00</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> bis </span> ' \
'<time datetime="2003-02-01 10:00">10:00</time>'
with language('en', 'US'):
df = datetime(2003, 2, 1, 9, 0)
dt = datetime(2003, 2, 1, 10, 0)
assert datetimerange(df, dt) == "02/01/2003 9 a.m. 10 a.m."
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">02/01/2003 9 a.m.</time> ' \
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">02/01/2003 9 a.m.</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2003-02-01 10:00">10 a.m.</time>'
@@ -170,11 +190,13 @@ def test_datetime_different_day():
df = datetime(2003, 2, 1, 9, 0)
dt = datetime(2003, 2, 2, 10, 0)
assert datetimerange(df, dt) == "01.02.2003 09:00 02.02.2003 10:00"
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">01.02.2003 09:00</time> ' \
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">01.02.2003 09:00</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> bis </span> ' \
'<time datetime="2003-02-02 10:00">02.02.2003 10:00</time>'
with language('en', 'US'):
df = datetime(2003, 2, 1, 9, 0)
dt = datetime(2003, 2, 2, 10, 0)
assert datetimerange(df, dt) == "02/01/2003 9 a.m. 02/02/2003 10 a.m."
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">02/01/2003 9 a.m.</time> ' \
assert datetimerange(df, dt, as_html=True) == '<time datetime="2003-02-01 09:00">02/01/2003 9 a.m.</time> ' \
'<span aria-hidden="true"></span><span class="sr-only"> until </span> ' \
'<time datetime="2003-02-02 10:00">02/02/2003 10 a.m.</time>'