Compare commits

..

33 Commits

Author SHA1 Message Date
Mira Weller
3689d4a5a0 Remove unused import 2025-11-05 12:20:24 +01:00
Mira Weller
867ea39a0d Improve log messages 2025-11-05 12:11:15 +01:00
Mira Weller
b060968f62 Remove EmailVerificationTokenGenerator 2025-11-05 11:48:04 +01:00
Mira Weller
9a47eb6385 Changes from review 2025-11-05 11:16:37 +01:00
Mira Weller
be67e40f1c add test to UserSettingsTest 2025-11-04 14:46:20 +01:00
Mira Weller
c99a9ebe9a make sure UserSettingsTest always uses correct <form> element by adding a testid 2025-11-04 14:44:08 +01:00
Mira Weller
b5cac90475 changing to same password as previous is already prevented by HistoryPasswordValidator
(would have to move this to UserPasswordChangeForm but decided to remove instead as it's redundant)
2025-11-04 14:36:19 +01:00
Mira Weller
58d36706b2 rebase migration 2025-10-30 16:50:36 +01:00
Mira Weller
c520f77bbb Merge branch 'master' into validate-user-email 2025-10-30 16:48:47 +01:00
Mira Weller
73ceeffc7f formatting 2025-10-30 16:36:26 +01:00
Mira Weller
7b6c82c341 Adapt test cases for email change form 2025-10-30 16:33:03 +01:00
Mira Weller
35ac277b3d Add email verification flow for existing users 2025-10-30 13:45:09 +01:00
Mira Weller
eb731f305b Use new control dialog style for confirmation code entry 2025-10-29 17:41:17 +01:00
Mira Weller
bf9af08cab Remove invalid id reference 2025-10-29 17:27:03 +01:00
Mira Weller
95639dc6e1 Add label text to confirmation code form 2025-10-29 17:25:37 +01:00
Mira Weller
966d6bb8e9 Fix PasswordRecoverForm in case of non-existing user 2025-09-30 15:22:22 +02:00
Mira Weller
2c20bf972f Rebase migration 2025-09-30 15:22:06 +02:00
Mira Weller
0deba91e4b Tests: password change tests need to run on the dedicated password change page 2025-09-30 15:15:36 +02:00
Mira Weller
b9b937ea0d Tests: testing that changing settings won't reset the needs_password_change no longer needed/possible, because settings are not available as long as needs_password_change is set 2025-09-30 15:15:36 +02:00
Mira Weller
410215f575 Tests: accept redirect to password change instead of settings 2025-09-30 15:15:36 +02:00
Mira Weller
1fa84b772b Fully block password change for non-native auth backend 2025-09-30 15:15:36 +02:00
Mira Weller
cda950befc Add success message 2025-09-30 15:15:36 +02:00
Mira Weller
783d51b75f Fix needs_password_change 2025-09-30 15:15:36 +02:00
Mira Weller
7333f82e45 Code formatting 2025-09-30 15:15:36 +02:00
Mira Weller
b2a4ba96f8 Improve confirmation code logic (store code in session, generate from SystemRandom)
Add docstrings
2025-09-30 15:15:36 +02:00
Mira Weller
81f5af8414 Add missing EmailVerificationTokenGenerator 2025-09-30 15:15:36 +02:00
Mira Weller
ce1406b158 Change button order 2025-09-30 15:15:36 +02:00
Mira Weller
b5ad68f48d Add "old email address" field 2025-09-30 15:15:36 +02:00
Mira Weller
5512fa8245 Improved style 2025-09-30 15:15:36 +02:00
Mira Weller
83f891ce24 fix default 2025-09-30 15:15:36 +02:00
Mira Weller
04e4e33885 add is_verified to admin user edit page 2025-09-30 15:15:36 +02:00
Mira Weller
2a98907e88 Improve email and password change forms, implement is_verified flag 2025-09-30 15:15:36 +02:00
Mira Weller
22e7962a29 Validation of user email addresses 2025-09-30 15:15:35 +02:00
45 changed files with 728 additions and 1602 deletions

View File

@@ -19,7 +19,6 @@ at :ref:`plugin-docs`.
item_bundles
item_add-ons
item_meta_properties
item_program_times
questions
question_options
quotas

View File

@@ -1,222 +0,0 @@
Item program times
==================
Resource description
--------------------
Program times for products (items) that can be set in addition to event times, e.g. to display seperate schedules within an event.
The program times resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the program time
start datetime The start date time for this program time slot.
end datetime The end date time for this program time slot.
===================================== ========================== =======================================================
.. versionchanged:: TODO
The resource has been added.
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/
Returns a list of all program times for a given item.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/items/11/program_times/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 2,
"start": "2025-08-14T22:00:00Z",
"end": "2025-08-15T00:00:00Z"
},
{
"id": 3,
"start": "2025-08-12T22:00:00Z",
"end": "2025-08-13T22:00:00Z"
},
{
"id": 14,
"start": "2025-08-15T22:00:00Z",
"end": "2025-08-17T22:00:00Z"
}
]
}
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param item: The ``id`` field of the item to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/item does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/(id)/
Returns information on one program time, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"start": "2025-08-15T22:00:00Z",
"end": "2025-10-27T23:00:00Z"
}
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param item: The ``id`` field of the item to fetch
:param id: The ``id`` field of the program time to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/
Creates a new program time
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"start": "2025-08-15T10:00:00Z",
"end": "2025-08-15T22:00:00Z"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"id": 17,
"start": "2025-08-15T10:00:00Z",
"end": "2025-08-15T22:00:00Z"
}
:param organizer: The ``slug`` field of the organizer of the event/item to create a program time for
:param event: The ``slug`` field of the event to create a program time for
:param item: The ``id`` field of the item to create a program time for
:statuscode 201: no error
:statuscode 400: The program time could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/program_times/(id)/
Update a program time. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
You can change all fields of the resource except the ``id`` field.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"start": "2025-08-14T10:00:00Z"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"start": "2025-08-14T10:00:00Z",
"end": "2025-08-15T12:00:00Z"
}
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the item to modify
:param id: The ``id`` field of the program time to modify
:statuscode 200: no error
:statuscode 400: The program time could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/program_times/(id)/
Delete a program time.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/program_times/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the item to modify
:param id: The ``id`` field of the program time to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.

View File

@@ -139,9 +139,6 @@ has_variations boolean Shows whether
variations list of objects A list with one object for each variation of this item.
Can be empty. Only writable during creation,
use separate endpoint to modify this later.
program_times list of objects A list with one object for each program time of this item.
Can be empty. Only writable during creation,
use separate endpoint to modify this later.
├ id integer Internal ID of the variation
├ value multi-lingual string The "name" of the variation
├ default_price money (string) The price set directly for this variation or ``null``
@@ -228,10 +225,6 @@ meta_data object Values set fo
The ``hidden_if_item_available_mode`` attributes has been added.
.. versionchanged:: 2025.9
The ``program_times`` attribute has been added.
Notes
-----
@@ -239,9 +232,9 @@ Please note that an item either always has variations or never has. Once created
change to an item without and vice versa. To create an item with variations ensure that you POST an item with at least
one variation.
Also note that ``variations``, ``bundles``, ``addons`` and ``program_times`` are only supported on ``POST``. To update/delete variations,
bundles, add-ons and program times please use the dedicated nested endpoints. By design this endpoint does not support ``PATCH`` and ``PUT``
with nested ``variations``, ``bundles``, ``addons`` and/or ``program_times``.
Also note that ``variations``, ``bundles``, and ``addons`` are only supported on ``POST``. To update/delete variations,
bundles, and add-ons please use the dedicated nested endpoints. By design this endpoint does not support ``PATCH`` and ``PUT``
with nested ``variations``, ``bundles`` and/or ``addons``.
Endpoints
---------
@@ -380,8 +373,7 @@ Endpoints
}
],
"addons": [],
"bundles": [],
"program_times": []
"bundles": []
}
]
}
@@ -533,8 +525,7 @@ Endpoints
}
],
"addons": [],
"bundles": [],
"program_times": []
"bundles": []
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -662,13 +653,7 @@ Endpoints
}
],
"addons": [],
"bundles": [],
"program_times": [
{
"start": "2025-08-14T22:00:00Z",
"end": "2025-08-15T00:00:00Z"
}
]
"bundles": []
}
**Example response**:
@@ -788,13 +773,7 @@ Endpoints
}
],
"addons": [],
"bundles": [],
"program_times": [
{
"start": "2025-08-14T22:00:00Z",
"end": "2025-08-15T00:00:00Z"
}
]
"bundles": []
}
:param organizer: The ``slug`` field of the organizer of the event to create an item for
@@ -810,9 +789,8 @@ Endpoints
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
You can change all fields of the resource except the ``has_variations``, ``variations``, ``addon`` and the
``program_times`` field. If you need to update/delete variations, add-ons or program times, please use the nested
dedicated endpoints.
You can change all fields of the resource except the ``has_variations``, ``variations`` and the ``addon`` field. If
you need to update/delete variations or add-ons please use the nested dedicated endpoints.
**Example request**:
@@ -946,8 +924,7 @@ Endpoints
}
],
"addons": [],
"bundles": [],
"program_times": []
"bundles": []
}
:param organizer: The ``slug`` field of the organizer to modify

View File

@@ -33,9 +33,9 @@ dependencies = [
"celery==5.5.*",
"chardet==5.2.*",
"cryptography>=44.0.0",
"css-inline==0.18.*",
"css-inline==0.17.*",
"defusedcsv>=1.1.0",
"Django[argon2]==4.2.*,>=4.2.26",
"Django[argon2]==4.2.*,>=4.2.24",
"django-bootstrap3==25.2",
"django-compressor==4.5.1",
"django-countries==7.6.*",

View File

@@ -47,9 +47,8 @@ from pretix.api.serializers.event import MetaDataField
from pretix.api.serializers.fields import UploadedFileField
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.base.models import (
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemProgramTime,
ItemVariation, ItemVariationMetaValue, Question, QuestionOption, Quota,
SalesChannel,
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemVariation,
ItemVariationMetaValue, Question, QuestionOption, Quota, SalesChannel,
)
@@ -188,12 +187,6 @@ class InlineItemAddOnSerializer(serializers.ModelSerializer):
'position', 'price_included', 'multi_allowed')
class InlineItemProgramTimeSerializer(serializers.ModelSerializer):
class Meta:
model = ItemProgramTime
fields = ('start', 'end')
class ItemBundleSerializer(serializers.ModelSerializer):
class Meta:
model = ItemBundle
@@ -219,31 +212,6 @@ class ItemBundleSerializer(serializers.ModelSerializer):
return data
class ItemProgramTimeSerializer(serializers.ModelSerializer):
class Meta:
model = ItemProgramTime
fields = ('id', 'start', 'end')
def validate(self, data):
data = super().validate(data)
full_data = self.to_internal_value(self.to_representation(self.instance)) if self.instance else {}
full_data.update(data)
start = full_data.get('start')
if not start:
raise ValidationError(_("The program start must not be empty."))
end = full_data.get('end')
if not end:
raise ValidationError(_("The program end must not be empty."))
if start > end:
raise ValidationError(_("The program end must not be before the program start."))
return data
class ItemAddOnSerializer(serializers.ModelSerializer):
class Meta:
model = ItemAddOn
@@ -282,7 +250,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
addons = InlineItemAddOnSerializer(many=True, required=False)
bundles = InlineItemBundleSerializer(many=True, required=False)
variations = InlineItemVariationSerializer(many=True, required=False)
program_times = InlineItemProgramTimeSerializer(many=True, required=False)
tax_rate = ItemTaxRateField(source='*', read_only=True)
meta_data = MetaDataField(required=False, source='*')
picture = UploadedFileField(required=False, allow_null=True, allowed_types=(
@@ -304,7 +271,7 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
'available_from', 'available_from_mode', 'available_until', 'available_until_mode',
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
'min_per_order', 'max_per_order', 'checkin_attention', 'checkin_text', 'has_variations', 'variations',
'addons', 'bundles', 'program_times', 'original_price', 'require_approval', 'generate_tickets',
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
'show_quota_left', 'hidden_if_available', 'hidden_if_item_available', 'hidden_if_item_available_mode', 'allow_waitinglist',
'issue_giftcard', 'meta_data',
'require_membership', 'require_membership_types', 'require_membership_hidden', 'grant_membership_type',
@@ -327,9 +294,9 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
def validate(self, data):
data = super().validate(data)
if self.instance and ('addons' in data or 'variations' in data or 'bundles' in data or 'program_times' in data):
raise ValidationError(_('Updating add-ons, bundles, program times or variations via PATCH/PUT is not '
'supported. Please use the dedicated nested endpoint.'))
if self.instance and ('addons' in data or 'variations' in data or 'bundles' in data):
raise ValidationError(_('Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use the '
'dedicated nested endpoint.'))
Item.clean_per_order(data.get('min_per_order'), data.get('max_per_order'))
Item.clean_available(data.get('available_from'), data.get('available_until'))
@@ -380,13 +347,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
ItemAddOn.clean_max_min_count(addon_data.get('max_count', 0), addon_data.get('min_count', 0))
return value
def validate_program_times(self, value):
if not self.instance:
for program_time_data in value:
ItemProgramTime.clean_start_end(self, start=program_time_data.get('start', None),
end=program_time_data.get('end', None))
return value
@cached_property
def item_meta_properties(self):
return {
@@ -404,7 +364,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
variations_data = validated_data.pop('variations') if 'variations' in validated_data else {}
addons_data = validated_data.pop('addons') if 'addons' in validated_data else {}
bundles_data = validated_data.pop('bundles') if 'bundles' in validated_data else {}
program_times_data = validated_data.pop('program_times') if 'program_times' in validated_data else {}
meta_data = validated_data.pop('meta_data', None)
picture = validated_data.pop('picture', None)
require_membership_types = validated_data.pop('require_membership_types', [])
@@ -439,8 +398,6 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
ItemAddOn.objects.create(base_item=item, **addon_data)
for bundle_data in bundles_data:
ItemBundle.objects.create(base_item=item, **bundle_data)
for program_time_data in program_times_data:
ItemProgramTime.objects.create(item=item, **program_time_data)
# Meta data
if meta_data is not None:

View File

@@ -112,7 +112,6 @@ item_router = routers.DefaultRouter()
item_router.register(r'variations', item.ItemVariationViewSet)
item_router.register(r'addons', item.ItemAddOnViewSet)
item_router.register(r'bundles', item.ItemBundleViewSet)
item_router.register(r'program_times', item.ItemProgramTimeViewSet)
order_router = routers.DefaultRouter()
order_router.register(r'payments', order.PaymentViewSet)

View File

@@ -46,13 +46,13 @@ from rest_framework.response import Response
from pretix.api.pagination import TotalOrderingFilter
from pretix.api.serializers.item import (
ItemAddOnSerializer, ItemBundleSerializer, ItemCategorySerializer,
ItemProgramTimeSerializer, ItemSerializer, ItemVariationSerializer,
QuestionOptionSerializer, QuestionSerializer, QuotaSerializer,
ItemSerializer, ItemVariationSerializer, QuestionOptionSerializer,
QuestionSerializer, QuotaSerializer,
)
from pretix.api.views import ConditionalListView
from pretix.base.models import (
CartPosition, Item, ItemAddOn, ItemBundle, ItemCategory, ItemProgramTime,
ItemVariation, Question, QuestionOption, Quota,
CartPosition, Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation,
Question, QuestionOption, Quota,
)
from pretix.base.services.quotas import QuotaAvailability
from pretix.helpers.dicts import merge_dicts
@@ -279,57 +279,6 @@ class ItemBundleViewSet(viewsets.ModelViewSet):
)
class ItemProgramTimeViewSet(viewsets.ModelViewSet):
serializer_class = ItemProgramTimeSerializer
queryset = ItemProgramTime.objects.none()
filter_backends = (DjangoFilterBackend, TotalOrderingFilter,)
ordering_fields = ('id',)
ordering = ('id',)
permission = None
write_permission = 'can_change_items'
@cached_property
def item(self):
return get_object_or_404(Item, pk=self.kwargs['item'], event=self.request.event)
def get_queryset(self):
return self.item.program_times.all()
def get_serializer_context(self):
ctx = super().get_serializer_context()
ctx['event'] = self.request.event
ctx['item'] = self.item
return ctx
def perform_create(self, serializer):
item = get_object_or_404(Item, pk=self.kwargs['item'], event=self.request.event)
serializer.save(item=item)
item.log_action(
'pretix.event.item.program_times.added',
user=self.request.user,
auth=self.request.auth,
data=merge_dicts(self.request.data, {'id': serializer.instance.pk})
)
def perform_update(self, serializer):
serializer.save(event=self.request.event)
serializer.instance.item.log_action(
'pretix.event.item.program_times.changed',
user=self.request.user,
auth=self.request.auth,
data=merge_dicts(self.request.data, {'id': serializer.instance.pk})
)
def perform_destroy(self, instance):
super().perform_destroy(instance)
instance.item.log_action(
'pretix.event.item.program_times.removed',
user=self.request.user,
auth=self.request.auth,
data={'start': instance.start, 'end': instance.end}
)
class ItemAddOnViewSet(viewsets.ModelViewSet):
serializer_class = ItemAddOnSerializer
queryset = ItemAddOn.objects.none()

View File

@@ -149,7 +149,7 @@ class ItemDataExporter(ListExporter):
row += [
_("Yes") if i.active and v.active else "",
", ".join([str(sn.label) for sn in sales_channels]),
v.default_price if v.default_price is not None else i.default_price,
v.default_price or i.default_price,
_("Yes") if i.free_price else "",
str(i.tax_rule) if i.tax_rule else "",
_("Yes") if i.admission else "",

View File

@@ -23,7 +23,6 @@ import datetime
import logging
import math
import re
import textwrap
import unicodedata
from collections import defaultdict
from decimal import Decimal
@@ -753,59 +752,11 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
return dt.astimezone(tz).date()
total = Decimal('0.00')
if has_taxes:
colwidths = [a * doc.width for a in (.50, .05, .15, .15, .15)]
else:
colwidths = [a * doc.width for a in (.65, .20, .15)]
for (description, tax_rate, tax_name, net_value, gross_value, subevent, period_start, period_end), lines in addon_aware_groupby(
all_lines,
key=_group_key,
is_addon=lambda l: l.description.startswith(" +"),
):
# split description into multiple Paragraphs so each fits in a table cell on a single page
# otherwise PDF-build fails
description_p_list = []
# normalize linebreaks to newlines instead of HTML so we can safely substring
description = description.replace('<br>', '<br />').replace('<br />\n', '\n').replace('<br />', '\n')
# start first line with different settings than the rest of the description
curr_description = description.split("\n", maxsplit=1)[0]
cellpadding = 6 # default cellpadding is only set on right side of column
max_width = colwidths[0] - cellpadding
max_height = self.stylesheet['Normal'].leading * 5
p_style = self.stylesheet['Normal']
for __ in range(1000):
p = FontFallbackParagraph(
self._clean_text(curr_description, tags=['br']),
p_style
)
h = p.wrap(max_width, doc.height)[1]
if h <= max_height:
description_p_list.append(p)
if curr_description == description:
break
description = description[len(curr_description):].lstrip()
curr_description = description.split("\n", maxsplit=1)[0]
# use different settings for all except first line
max_width = sum(colwidths[0:3 if has_taxes else 2]) - cellpadding
max_height = self.stylesheet['Fineprint'].leading * 8
p_style = self.stylesheet['Fineprint']
continue
if not description_p_list:
# first "manual" line is larger than 5 "real" lines => only allow one line and set rest in Fineprint
max_height = self.stylesheet['Normal'].leading
if h > max_height * 1.1:
# quickly bring the text-length down to a managable length to then stepwise reduce
wrap_to = math.ceil(len(curr_description) * max_height * 1.1 / h)
else:
# trim to 95% length, but at most 10 chars to not have strangely short lines in the middle of a paragraph
wrap_to = max(len(curr_description) - 10, math.ceil(len(curr_description) * 0.95))
curr_description = textwrap.wrap(curr_description, wrap_to, replace_whitespace=False, drop_whitespace=False)[0]
# Try to be clever and figure out when organizers would want to show the period. This heuristic is
# not perfect and the only "fully correct" way would be to include the period on every line always,
# however this will cause confusion (a) due to useless repetition of the same date all over the invoice
@@ -859,10 +810,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
# Group together at the end of the invoice
request_show_service_date = period_line
elif period_line:
description_p_list.append(FontFallbackParagraph(
period_line,
self.stylesheet['Fineprint']
))
description += "\n" + period_line
lines = list(lines)
if has_taxes:
@@ -871,13 +819,13 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
net_price=money_filter(net_value, self.invoice.event.currency),
gross_price=money_filter(gross_value, self.invoice.event.currency),
)
description_p_list.append(FontFallbackParagraph(
single_price_line,
self.stylesheet['Fineprint']
))
description = description + "\n" + single_price_line
tdata.append((
description_p_list.pop(0),
FontFallbackParagraph(
self._clean_text(description, tags=['br']),
self.stylesheet['Normal']
),
str(len(lines)),
localize(tax_rate) + " %",
FontFallbackParagraph(
@@ -889,52 +837,23 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
self.stylesheet['NormalRight']
),
))
for p in description_p_list:
tdata.append((p, "", "", "", ""))
tstyledata.append((
'SPAN',
(0, len(tdata) - 1),
(2, len(tdata) - 1),
))
else:
if len(lines) > 1:
single_price_line = pgettext('invoice', 'Single price: {price}').format(
price=money_filter(gross_value, self.invoice.event.currency),
)
description_p_list.append(FontFallbackParagraph(
single_price_line,
self.stylesheet['Fineprint']
))
description = description + "\n" + single_price_line
tdata.append((
description_p_list.pop(0),
FontFallbackParagraph(
self._clean_text(description, tags=['br']),
self.stylesheet['Normal']
),
str(len(lines)),
FontFallbackParagraph(
money_filter(gross_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
self.stylesheet['NormalRight']
),
))
for p in description_p_list:
tdata.append((p, "", ""))
tstyledata.append((
'SPAN',
(0, len(tdata) - 1),
(1, len(tdata) - 1),
))
tstyledata += [
(
'BOTTOMPADDING',
(0, len(tdata) - len(description_p_list)),
(-1, len(tdata) - 2),
0
),
(
'TOPPADDING',
(0, len(tdata) - len(description_p_list)),
(-1, len(tdata) - 1),
0
),
]
taxvalue_map[tax_rate, tax_name] += (gross_value - net_value) * len(lines)
grossvalue_map[tax_rate, tax_name] += gross_value * len(lines)
total += gross_value * len(lines)
@@ -944,11 +863,13 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '', '', '',
money_filter(total, self.invoice.event.currency)
])
colwidths = [a * doc.width for a in (.50, .05, .15, .15, .15)]
else:
tdata.append([
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '',
money_filter(total, self.invoice.event.currency)
])
colwidths = [a * doc.width for a in (.65, .20, .15)]
if not self.invoice.is_cancellation:
if self.invoice.event.settings.invoice_show_payments and self.invoice.order.status == Order.STATUS_PENDING:

View File

@@ -1,25 +0,0 @@
# Generated by Django 4.2.19 on 2025-08-11 10:25
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0293_cartposition_price_includes_rounding_correction_and_more'),
]
operations = [
migrations.CreateModel(
name='ItemProgramTime',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
('start', models.DateTimeField()),
('end', models.DateTimeField()),
('item',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='program_times',
to='pretixbase.item')),
],
),
]

View File

@@ -6,7 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0294_item_program_time"),
("pretixbase", "0293_cartposition_price_includes_rounding_correction_and_more"),
]
operations = [

View File

@@ -36,9 +36,8 @@ from .giftcards import GiftCard, GiftCardAcceptance, GiftCardTransaction
from .invoices import Invoice, InvoiceLine, invoice_filename
from .items import (
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaProperty, ItemMetaValue,
ItemProgramTime, ItemVariation, ItemVariationMetaValue, Question,
QuestionOption, Quota, SubEventItem, SubEventItemVariation,
itempicture_upload_to,
ItemVariation, ItemVariationMetaValue, Question, QuestionOption, Quota,
SubEventItem, SubEventItemVariation, itempicture_upload_to,
)
from .log import LogEntry
from .media import ReusableMedium

View File

@@ -715,13 +715,6 @@ class Event(EventMixin, LoggedModel):
self.settings.name_scheme = 'given_family'
self.settings.payment_banktransfer_invoice_immediately = True
self.settings.low_availability_percentage = 10
self.settings.mail_send_order_free_attendee = True
self.settings.mail_send_order_placed_attendee = True
self.settings.mail_send_order_placed_attendee = True
self.settings.mail_send_order_paid_attendee = True
self.settings.mail_send_order_approved_attendee = True
self.settings.mail_send_order_approved_free_attendee = True
self.settings.mail_text_download_reminder_attendee = True
@property
def social_image(self):
@@ -854,7 +847,7 @@ class Event(EventMixin, LoggedModel):
from ..signals import event_copy_data
from . import (
Discount, Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue,
ItemProgramTime, ItemVariationMetaValue, Question, Quota,
ItemVariationMetaValue, Question, Quota,
)
# Note: avoid self.set_active_plugins(), it causes trouble e.g. for the badges plugin.
@@ -997,11 +990,6 @@ class Event(EventMixin, LoggedModel):
ia.bundled_variation = variation_map[ia.bundled_variation.pk]
ia.save(force_insert=True)
for ipt in ItemProgramTime.objects.filter(item__event=other).prefetch_related('item'):
ipt.pk = None
ipt.item = item_map[ipt.item.pk]
ipt.save(force_insert=True)
quota_map = {}
for q in Quota.objects.filter(event=other, subevent__isnull=True).prefetch_related('items', 'variations'):
quota_map[q.pk] = q

View File

@@ -2294,27 +2294,3 @@ class ItemVariationMetaValue(LoggedModel):
class Meta:
unique_together = ('variation', 'property')
class ItemProgramTime(models.Model):
"""
This model can be used to add a program time to an item.
:param item: The item the program time applies to
:type item: Item
:param start: The date and time this program time starts
:type start: datetime
:param end: The date and time this program time ends
:type end: datetime
"""
item = models.ForeignKey('Item', related_name='program_times', on_delete=models.CASCADE)
start = models.DateTimeField(verbose_name=_("Start"))
end = models.DateTimeField(verbose_name=_("End"))
def clean(self):
self.clean_start_end(start=self.start, end=self.end)
super().clean()
def clean_start_end(self, start: datetime = None, end: datetime = None):
if start and end and start > end:
raise ValidationError(_("The program end must not be before the program start."))

View File

@@ -280,13 +280,13 @@ class Seat(models.Model):
def is_available(self, ignore_cart=None, ignore_orderpos=None, ignore_voucher_id=None,
sales_channel='web',
ignore_distancing=False, distance_ignore_cart_id=None, always_allow_blocked=False):
ignore_distancing=False, distance_ignore_cart_id=None):
from .orders import Order
from .organizer import SalesChannel
if isinstance(sales_channel, SalesChannel):
sales_channel = sales_channel.identifier
if not always_allow_blocked and self.blocked and sales_channel not in self.event.settings.seating_allow_blocked_seats_for_channel:
if self.blocked and sales_channel not in self.event.settings.seating_allow_blocked_seats_for_channel:
return False
opqs = self.orderposition_set.filter(
order__status__in=[Order.STATUS_PENDING, Order.STATUS_PAID],

View File

@@ -1377,7 +1377,7 @@ class GiftCardPayment(BasePaymentProvider):
execute_payment_needs_user = False
verbose_name = _("Gift card")
payment_form_class = GiftCardPaymentForm
payment_form_template_name = 'pretixpresale/giftcard/checkout.html'
payment_form_template_name = 'pretixcontrol/giftcards/checkout.html'
@cached_property
def customer_gift_cards(self):
@@ -1504,7 +1504,7 @@ class GiftCardPayment(BasePaymentProvider):
return super().order_change_allowed(order) and self.event.organizer.has_gift_cards
def checkout_confirm_render(self, request, order=None, info_data=None) -> str:
return get_template('pretixpresale/giftcard/checkout_confirm.html').render({
return get_template('pretixcontrol/giftcards/checkout_confirm.html').render({
'info_data': info_data,
})

View File

@@ -84,7 +84,6 @@ from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.base.signals import layout_image_variables, layout_text_variables
from pretix.base.templatetags.money import money_filter
from pretix.base.templatetags.phone_format import phone_format
from pretix.helpers.daterange import datetimerange
from pretix.helpers.reportlab import ThumbnailingImageReader, reshaper
from pretix.presale.style import get_fonts
@@ -491,12 +490,6 @@ DEFAULT_VARIABLES = OrderedDict((
"TIME_FORMAT"
) if op.valid_until else ""
}),
("program_times", {
"label": _("Program times: date and time"),
"editor_sample": _(
"2017-05-31 10:00 12:00\n2017-05-31 14:00 16:00\n2017-05-31 14:00 2017-06-01 14:00"),
"evaluate": lambda op, order, ev: get_program_times(op, ev)
}),
("medium_identifier", {
"label": _("Reusable Medium ID"),
"editor_sample": "ABC1234DEF4567",
@@ -741,16 +734,6 @@ def get_seat(op: OrderPosition):
return None
def get_program_times(op: OrderPosition, ev: Event):
return '\n'.join([
datetimerange(
pt.start.astimezone(ev.timezone),
pt.end.astimezone(ev.timezone),
as_html=False
) for pt in op.item.program_times.all()
])
def generate_compressed_addon_list(op, order, event):
itemcount = defaultdict(int)
addons = [p for p in (

View File

@@ -258,15 +258,9 @@ def build_invoice(invoice: Invoice) -> Invoice:
if resp:
desc += "<br/>" + resp
answers_qs = p.answers.filter(
question__print_on_invoice=True
).select_related(
'question'
).order_by(
'question__position',
'question__id'
)
for answ in answers_qs:
for answ in p.answers.all():
if not answ.question.print_on_invoice:
continue
desc += "<br />{}{} {}".format(
answ.question.question,
"" if str(answ.question.question).endswith("?") else ":",

View File

@@ -1670,14 +1670,13 @@ class OrderChangeManager:
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
def __init__(self, order: Order, user=None, auth=None, notify=True, reissue_invoice=True, allow_blocked_seats=False):
def __init__(self, order: Order, user=None, auth=None, notify=True, reissue_invoice=True):
self.order = order
self.user = user
self.auth = auth
self.event = order.event
self.split_order = None
self.reissue_invoice = reissue_invoice
self.allow_blocked_seats = allow_blocked_seats
self._committed = False
self._totaldiff_guesstimate = 0
self._quotadiff = Counter()
@@ -2198,7 +2197,7 @@ class OrderChangeManager:
for seat, diff in self._seatdiff.items():
if diff <= 0:
continue
if not seat.is_available(sales_channel=self.order.sales_channel, ignore_distancing=True, always_allow_blocked=self.allow_blocked_seats) or diff > 1:
if not seat.is_available(sales_channel=self.order.sales_channel, ignore_distancing=True) or diff > 1:
raise OrderError(self.error_messages['seat_unavailable'].format(seat=seat.name))
if self.event.has_subevents:

View File

@@ -56,8 +56,7 @@ from i18nfield.forms import I18nFormField, I18nTextarea
from pretix.base.forms import I18nFormSet, I18nMarkdownTextarea, I18nModelForm
from pretix.base.forms.widgets import DatePickerWidget
from pretix.base.models import (
Item, ItemCategory, ItemProgramTime, ItemVariation, Question,
QuestionOption, Quota,
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
)
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
from pretix.base.signals import item_copy_data
@@ -573,8 +572,6 @@ class ItemCreateForm(I18nModelForm):
for b in self.cleaned_data['copy_from'].bundles.all():
instance.bundles.create(bundled_item=b.bundled_item, bundled_variation=b.bundled_variation,
count=b.count, designated_price=b.designated_price)
for pt in self.cleaned_data['copy_from'].program_times.all():
instance.program_times.create(start=pt.start, end=pt.end)
item_copy_data.send(sender=self.event, source=self.cleaned_data['copy_from'], target=instance)
@@ -1324,49 +1321,3 @@ class ItemMetaValueForm(forms.ModelForm):
widgets = {
'value': forms.TextInput()
}
class ItemProgramTimeFormSet(I18nFormSet):
template = "pretixcontrol/item/include_program_times.html"
title = _('Program times')
def _construct_form(self, i, **kwargs):
kwargs['event'] = self.event
return super()._construct_form(i, **kwargs)
@property
def empty_form(self):
self.is_valid()
form = self.form(
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
locales=self.locales,
event=self.event
)
self.add_fields(form, None)
return form
class ItemProgramTimeForm(I18nModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['end'].widget.attrs['data-date-after'] = '#id_{prefix}-start_0'.format(prefix=self.prefix)
class Meta:
model = ItemProgramTime
localized_fields = '__all__'
fields = [
'start',
'end',
]
field_classes = {
'start': forms.SplitDateTimeField,
'end': forms.SplitDateTimeField,
}
widgets = {
'start': SplitDateTimePickerWidget(),
'end': SplitDateTimePickerWidget(),
}

View File

@@ -890,9 +890,6 @@ class EventPluginStateLogEntryType(EventLogEntryType):
'pretix.event.item.bundles.added': _('A bundled item has been added to this product.'),
'pretix.event.item.bundles.removed': _('A bundled item has been removed from this product.'),
'pretix.event.item.bundles.changed': _('A bundled item has been changed on this product.'),
'pretix.event.item.program_times.added': _('A program time has been added to this product.'),
'pretix.event.item.program_times.changed': _('A program time has been changed on this product.'),
'pretix.event.item.program_times.removed': _('A program time has been removed from this product.'),
})
class CoreItemLogEntryType(ItemLogEntryType):
pass

View File

@@ -0,0 +1,35 @@
{% load i18n %}
{% load bootstrap3 %}
{% load money %}
{% load rich_text %}
{{ request.event.settings.payment_giftcard_public_description|rich_text }}
{% if customer_gift_cards %}
<p><strong>
<span class="sr-only">{% trans "Information" %}</span>
{% trans "The following gift cards are available in your customer account:" %}
</strong></p>
<form method="post">
{% csrf_token %}
<ul class="list-group">
{% for c in customer_gift_cards %}
<li class="list-group-item row row-no-gutters">
<div class="col-sm-8 col-md-9" id="gc-code-{{ forloop.counter }}">
{{ c }}
</div>
<div class="col-sm-2 text-right" id="gc-value-{{ forloop.counter }}">
{{ c.value|money:c.currency }}
</div>
<div class="col-sm-2 col-md-1 text-right">
<button name="use_giftcard" class="btn btn-primary btn-xs use_giftcard" data-value="{{ c.secret }}"
title="{% trans "Use gift card" %}"
aria-describedby="gc-code-{{ forloop.counter }} gc-value-{{ forloop.counter }}">
{% trans "Apply" %}
</button>
</div>
</li>
{% endfor %}
</ul>
</form>
{% endif %}
{% bootstrap_form form layout='checkout' %}

View File

@@ -1,70 +0,0 @@
{% load i18n %}
{% load bootstrap3 %}
{% load formset_tags %}
<p>
{% blocktrans trimmed %}
With program times, you can set specific dates and times for this product.
This is useful if this product represents access to parts of your event that happen at different times than your event in general.
This will not affect access control, but will affect calendar invites and ticket output.
{% endblocktrans %}
</p>
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
{{ formset.management_form }}
{% bootstrap_formset_errors formset %}
<div data-formset-body>
{% for form in formset %}
<div class="panel panel-default" data-formset-form>
<div class="sr-only">
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="panel-heading">
<div class="row">
<div class="col-sm-8">
<h3 class="panel-title">{% trans "Program time" %}</h3>
</div>
<div class="col-sm-4 text-right flip">
<button type="button" class="btn btn-xs btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
</div>
<div class="panel-body form-horizontal">
{% bootstrap_form_errors form %}
{% bootstrap_field form.start layout="control" %}
{% bootstrap_field form.end layout="control" %}
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div class="panel panel-default" data-formset-form>
<div class="sr-only">
{{ formset.empty_form.id }}
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="panel-heading">
<div class="row">
<div class="col-sm-8">
<h3 class="panel-title">{% trans "Program time" %}</h3>
</div>
<div class="col-sm-4 text-right flip">
<button type="button" class="btn btn-xs btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
</div>
<div class="panel-body form-horizontal">
{% bootstrap_field formset.empty_form.start layout="control" %}
{% bootstrap_field formset.empty_form.end layout="control" %}
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-default" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add a program time" %}</button>
</p>
</div>

View File

@@ -769,12 +769,10 @@
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ items.total|money:event.currency }}</strong>
{% if django_settings.DEBUG %}
<br/>
<small class="admin-only">
tax_rounding_mode = {{ order.tax_rounding_mode }}
</small>
{% endif %}
<br/>
<small class="admin-only">
tax_rounding_mode = {{ order.tax_rounding_mode }}
</small>
</div>
<div class="clearfix"></div>
</div>

View File

@@ -60,14 +60,13 @@ from django.views.generic.detail import DetailView, SingleObjectMixin
from django_countries.fields import Country
from pretix.api.serializers.item import (
ItemAddOnSerializer, ItemBundleSerializer, ItemProgramTimeSerializer,
ItemVariationSerializer,
ItemAddOnSerializer, ItemBundleSerializer, ItemVariationSerializer,
)
from pretix.base.forms import I18nFormSet
from pretix.base.models import (
CartPosition, Item, ItemCategory, ItemProgramTime, ItemVariation, Order,
OrderPosition, Question, QuestionAnswer, QuestionOption, Quota,
SeatCategoryMapping, Voucher,
CartPosition, Item, ItemCategory, ItemVariation, Order, OrderPosition,
Question, QuestionAnswer, QuestionOption, Quota, SeatCategoryMapping,
Voucher,
)
from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
@@ -76,9 +75,9 @@ from pretix.base.services.tickets import invalidate_cache
from pretix.base.signals import quota_availability
from pretix.control.forms.item import (
CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemBundleForm,
ItemBundleFormSet, ItemCreateForm, ItemMetaValueForm, ItemProgramTimeForm,
ItemProgramTimeFormSet, ItemUpdateForm, ItemVariationForm,
ItemVariationsFormSet, QuestionForm, QuestionOptionForm, QuotaForm,
ItemBundleFormSet, ItemCreateForm, ItemMetaValueForm, ItemUpdateForm,
ItemVariationForm, ItemVariationsFormSet, QuestionForm, QuestionOptionForm,
QuotaForm,
)
from pretix.control.permissions import (
EventPermissionRequiredMixin, event_permission_required,
@@ -1432,8 +1431,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataE
form.instance.position = i
setattr(form.instance, attr, self.get_object())
created = not form.instance.pk
if form.has_changed():
form.save()
form.save()
if form.has_changed() and any(a for a in form.changed_data if a != 'ORDER'):
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
if key == 'variations':
@@ -1499,16 +1497,6 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataE
'bundles', 'bundles', 'base_item', order=False,
serializer=ItemBundleSerializer
)
elif k == 'program_times':
self.save_formset(
'program_times', 'program_times', order=False,
serializer=ItemProgramTimeSerializer
)
if not change_data:
for f in v.forms:
if (f in v.deleted_forms and f.instance.pk) or f.has_changed():
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'item': self.object.pk})
break
else:
v.save()
@@ -1571,20 +1559,9 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataE
queryset=ItemBundle.objects.filter(base_item=self.get_object()),
event=self.request.event, item=self.item, prefix="bundles"
)),
('program_times', inlineformset_factory(
Item, ItemProgramTime,
form=ItemProgramTimeForm, formset=ItemProgramTimeFormSet,
can_order=False, can_delete=True, extra=0
)(
self.request.POST if self.request.method == "POST" else None,
queryset=ItemProgramTime.objects.filter(item=self.get_object()),
event=self.request.event, prefix="program_times"
)),
])
if not self.object.has_variations:
del f['variations']
if self.item.event.has_subevents:
del f['program_times']
i = 0
for rec, resp in item_formsets.send(sender=self.request.event, item=self.item, request=self.request):

View File

@@ -2146,8 +2146,7 @@ class OrderChange(OrderView):
self.order,
user=self.request.user,
notify=notify,
reissue_invoice=self.other_form.cleaned_data['reissue_invoice'] if self.other_form.is_valid() else True,
allow_blocked_seats=True,
reissue_invoice=self.other_form.cleaned_data['reissue_invoice'] if self.other_form.is_valid() else True
)
form_valid = (self._process_add_fees(ocm) and
self._process_add_positions(ocm) and

View File

@@ -44,9 +44,7 @@ from pypdf.errors import PdfReadError
from reportlab.lib.units import mm
from pretix.base.i18n import language
from pretix.base.models import (
CachedFile, InvoiceAddress, ItemProgramTime, OrderPosition,
)
from pretix.base.models import CachedFile, InvoiceAddress, OrderPosition
from pretix.base.pdf import get_images, get_variables
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.control.permissions import EventPermissionRequiredMixin
@@ -97,9 +95,6 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
description=_("Sample product description"))
item2 = self.request.event.items.create(name=_("Sample workshop"), default_price=Decimal('23.40'))
ItemProgramTime.objects.create(start=now(), end=now(), item=item)
ItemProgramTime.objects.create(start=now(), end=now(), item=item2)
from pretix.base.models import Order
order = self.request.event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
email='sample@pretix.eu',

View File

@@ -8,10 +8,10 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-29 07:55+0000\n"
"PO-Revision-Date: 2025-10-31 17:00+0000\n"
"PO-Revision-Date: 2025-10-28 17:00+0000\n"
"Last-Translator: Núria Masclans <nuriamasclansserrat@gmail.com>\n"
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/"
"pretix-js/ca/>\n"
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
"js/ca/>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -651,8 +651,6 @@ msgid ""
"Your color has insufficient contrast to white. Accessibility of your site "
"will be impacted."
msgstr ""
"El color no té prou contrast amb el blanc i pot afectar a l'accessibilitat "
"del lloc web."
#: pretix/static/pretixcontrol/js/ui/main.js:418
#: pretix/static/pretixcontrol/js/ui/main.js:438
@@ -714,226 +712,229 @@ msgstr[0] "(una data més)"
msgstr[1] "({num} dates més)"
#: pretix/static/pretixpresale/js/ui/cart.js:47
#, fuzzy
#| msgid "The items in your cart are no longer reserved for you."
msgid ""
"The items in your cart are no longer reserved for you. You can still "
"complete your order as long as theyre available."
msgstr ""
"Ja no tens reservat el contingut de la cistella. Encara pots completar la "
"comanda si els articles seleccionats continuen disponibles."
msgstr "El contingut de la cistella ja no el teniu reservat."
#: pretix/static/pretixpresale/js/ui/cart.js:49
msgid "Cart expired"
msgstr "Cistella caducada"
msgstr "Cistella expirada"
#: pretix/static/pretixpresale/js/ui/cart.js:58
#: pretix/static/pretixpresale/js/ui/cart.js:84
msgid "Your cart is about to expire."
msgstr "La teva cistella està a punt de caducar."
msgstr ""
#: pretix/static/pretixpresale/js/ui/cart.js:62
#, fuzzy
#| msgid "The items in your cart are no longer reserved for you."
msgid "The items in your cart are reserved for you for one minute."
msgid_plural "The items in your cart are reserved for you for {num} minutes."
msgstr[0] "El contingut de la teva cistella està reservat durant un minut."
msgstr[1] "El contingut de la teva cistella està reservat durant {num} minuts."
msgstr[0] "El contingut de la cistella ja no el teniu reservat."
msgstr[1] "El contingut de la cistella ja no el teniu reservat."
#: pretix/static/pretixpresale/js/ui/cart.js:83
#, fuzzy
#| msgid "Cart expired"
msgid "Your cart has expired."
msgstr "La teva cistella ha caducat."
msgstr "Cistella expirada"
#: pretix/static/pretixpresale/js/ui/cart.js:86
#, fuzzy
#| msgid "The items in your cart are no longer reserved for you."
msgid ""
"The items in your cart are no longer reserved for you. You can still "
"complete your order as long as they're available."
msgstr ""
"Ja no teniu reservat el contingut de la cistella. Encara podeu completar la "
"comanda si els articles continuen disponibles."
msgstr "El contingut de la cistella ja no el teniu reservat."
#: pretix/static/pretixpresale/js/ui/cart.js:87
msgid "Do you want to renew the reservation period?"
msgstr "Vols ampliar el temps de reserva?"
msgstr ""
#: pretix/static/pretixpresale/js/ui/cart.js:90
msgid "Renew reservation"
msgstr "Renovar reserva"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:194
msgid "The organizer keeps %(currency)s %(amount)s"
msgstr "L'entitat organitzadora es queda %(currency)s %(amount)s"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:202
msgid "You get %(currency)s %(amount)s back"
msgstr "Rebràs %(currency)s %(amount)s"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:218
msgid "Please enter the amount the organizer can keep."
msgstr "Introdueix limport que es queda lorganitzador."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:570
msgid "Your local time:"
msgstr "La teva hora local:"
msgstr ""
#: pretix/static/pretixpresale/js/walletdetection.js:39
#, fuzzy
msgid "Google Pay"
msgstr "Google Pay"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:16
msgctxt "widget"
msgid "Quantity"
msgstr "Quantitat"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:17
msgctxt "widget"
msgid "Decrease quantity"
msgstr "Disminueix quantitat"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:18
msgctxt "widget"
msgid "Increase quantity"
msgstr "Augmenta quantitat"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:19
msgctxt "widget"
msgid "Filter events by"
msgstr "Filtra els esdeveniments per"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:20
msgctxt "widget"
msgid "Filter"
msgstr "Filtra"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:21
msgctxt "widget"
msgid "Price"
msgstr "Preu"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:22
#, javascript-format
msgctxt "widget"
msgid "Original price: %s"
msgstr "Preu original: %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:23
#, javascript-format
msgctxt "widget"
msgid "New price: %s"
msgstr "Nou preu: %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:24
msgctxt "widget"
msgid "Select"
msgstr "Selecciona"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:25
#, javascript-format
msgctxt "widget"
msgid "Select %s"
msgstr "Selecciona %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:26
#, javascript-format
msgctxt "widget"
msgid "Select variant %s"
msgstr "Selecciona la variant %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:27
msgctxt "widget"
msgid "Sold out"
msgstr "Esgotat"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:28
msgctxt "widget"
msgid "Buy"
msgstr "Compra"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:29
msgctxt "widget"
msgid "Register"
msgstr "Registrar-vos"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:30
msgctxt "widget"
msgid "Reserved"
msgstr "Reservat"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:31
msgctxt "widget"
msgid "FREE"
msgstr "GRATUÏT"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:32
msgctxt "widget"
msgid "from %(currency)s %(price)s"
msgstr "des de %(price)s %(currency)s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:33
#, javascript-format
msgctxt "widget"
msgid "Image of %s"
msgstr "Imatge de %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:34
msgctxt "widget"
msgid "incl. %(rate)s% %(taxname)s"
msgstr "Inclòs %(rate)s% %(taxname)s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:35
msgctxt "widget"
msgid "plus %(rate)s% %(taxname)s"
msgstr "més %(rate)s% %(taxname)s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"
msgid "incl. taxes"
msgstr "incl. impostos"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:37
msgctxt "widget"
msgid "plus taxes"
msgstr "més impostos"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:38
#, javascript-format
msgctxt "widget"
msgid "currently available: %s"
msgstr "disponibles: %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:39
msgctxt "widget"
msgid "Only available with a voucher"
msgstr "Només disponible amb un cupó"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:40
#: pretix/static/pretixpresale/js/widget/widget.js:43
msgctxt "widget"
msgid "Not yet available"
msgstr "Encara no disponible"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:41
msgctxt "widget"
msgid "Not available anymore"
msgstr "Ja no està disponible"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:42
msgctxt "widget"
msgid "Currently not available"
msgstr "No disponible"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:44
#, javascript-format
msgctxt "widget"
msgid "minimum amount to order: %s"
msgstr "Comanda mínima: %s"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:45
msgctxt "widget"
msgid "Close ticket shop"
msgstr "Tanca la botiga d'entrades"
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:46
msgctxt "widget"
msgid "The ticket shop could not be loaded."
msgstr "No s'ha pogut carregar la botiga d'entrades."
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:47
msgctxt "widget"

View File

@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-30 10:55+0000\n"
"PO-Revision-Date: 2025-10-30 20:00+0000\n"
"PO-Revision-Date: 2025-10-29 09:24+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix/de/"
">\n"
@@ -9664,15 +9664,15 @@ msgstr "Der Gutschein wurde an {recipient} verschickt."
#: pretix/base/settings.py:81
msgid "Compute taxes for every line individually"
msgstr "Berechne Steuern für jede Position einzeln"
msgstr ""
#: pretix/base/settings.py:82
msgid "Compute taxes based on net total"
msgstr "Berechne Steuern auf Basis der Nettosumme"
msgstr ""
#: pretix/base/settings.py:83
msgid "Compute taxes based on net total with stable gross prices"
msgstr "Berechne Steuern auf Basis der Nettosumme mit konstanten Bruttopreisen"
msgstr ""
#: pretix/base/settings.py:133
msgid "Allow usage of restricted plugins"
@@ -9762,8 +9762,13 @@ msgid "Add-on products will not be counted."
msgstr "Zusatzprodukte werden nicht mitgezählt."
#: pretix/base/settings.py:334
#, fuzzy
#| msgid ""
#| "Show net prices instead of gross prices in the product list (not "
#| "recommended!)"
msgid "Show net prices instead of gross prices in the product list"
msgstr "Zeigen Nettopreise statt Bruttopreisen in der Produktliste"
msgstr ""
"Zeige Netto- statt Bruttopreisen in den Produktlisten (nicht empfohlen)"
#: pretix/base/settings.py:335
msgid ""
@@ -9880,8 +9885,10 @@ msgid "Require a phone number per order"
msgstr "Telefonnummer pro Bestellung erfordern"
#: pretix/base/settings.py:481
#, fuzzy
#| msgid "including all taxes"
msgid "Rounding of taxes"
msgstr "Rundung der Steuern"
msgstr "inklusive aller Steuern"
#: pretix/base/settings.py:485
msgid ""
@@ -9889,10 +9896,6 @@ msgid ""
"for tax reporting, you need to make sure to account for possible rounding "
"differences if your external system rounds differently than pretix."
msgstr ""
"Bitte beachten Sie, dass bei der Übertragung der Verkaufsdaten in ein "
"externes Buchhaltungssystem darauf geachtet werden muss, dass potentielle "
"Rundungsabweichungen behandelt werden, wenn das externe System anders rundet "
"als pretix."
#: pretix/base/settings.py:500
msgid "Ask for invoice address"
@@ -14034,24 +14037,31 @@ msgstr ""
"Ausstellung ablaufen."
#: pretix/control/forms/event.py:806
#, fuzzy
#| msgid "including all taxes"
msgid "Prices including tax"
msgstr "Preis inklusive Steuern"
msgstr "inklusive aller Steuern"
#: pretix/control/forms/event.py:807
msgid "Recommended if you sell tickets at least partly to consumers."
msgstr "Empfohlen, wenn mindestens teilweise an Verbraucher verkauft wird."
msgstr ""
#: pretix/control/forms/event.py:811
#, fuzzy
#| msgctxt "reporting_timeframe"
#| msgid "All future (excluding today)"
msgid "Prices excluding tax"
msgstr "Preise exklusive Steuern"
msgstr "Zukunft (ab morgen)"
#: pretix/control/forms/event.py:812
msgid "Recommended only if you sell tickets primarily to business customers."
msgstr "Empfohlen, wenn primär an Geschäftskunden verkauft wird."
msgstr ""
#: pretix/control/forms/event.py:848
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Prices shown to customer"
msgstr "Preisanzeige für Kunden"
msgstr "Wunschdatum des Kunden"
#: pretix/control/forms/event.py:852
msgid ""
@@ -14060,10 +14070,6 @@ msgid ""
"product, the total tax amount can differ from when it would be computed from "
"the order total."
msgstr ""
"Empfohlen, wenn keine E-Rechnungen benötigt werden. Jedes Produkt wird zum "
"beworbenen Netto- und Bruttopreis verkauft. Im Fall von Bestellungen mit "
"mehreren Produkten kann die Gesamt-Steuersumme höher oder niedriger sein als "
"die, die sich aus der Bestellsumme berechnen würde."
#: pretix/control/forms/event.py:857
msgid ""
@@ -14072,11 +14078,6 @@ msgid ""
"may be changed to ensure correct rounding, while the net prices will be kept "
"as configured. This may cause the actual payment amount to differ."
msgstr ""
"Empfohlen für E-Rechnungen, wenn primär an Geschäftskunden verkauft wird und "
"Kunden Nettopreise angezeigt werden. Der Bruttopreis einzelner Produkte kann "
"sich automatisch ändern, um ein korrektes Rundungsverhalten sicherzustellen, "
"während die Nettopreise immer den eingestellten Preisen entsprechen. Der "
"resultierende Zahlungsbetrag kann durch die Rundung abweichen."
#: pretix/control/forms/event.py:863
msgid ""
@@ -14086,13 +14087,6 @@ msgid ""
"configured whenever possible. Gross prices may still change if they are "
"impossible to derive from a rounded net price."
msgstr ""
"Empfohlen für E-Rechnungen, wenn primär an Verbraucher verkauft wird und "
"Kunden Bruttopreise angezeigt werden. Der Netto- oder Bruttopreis einzelner "
"Produkte kann sich automatisch ändern, um ein korrektes Rundungsverhalten "
"sicherzustellen. Dabei versucht das System, die Bruttopreise möglichst bei "
"den eingestellten Preisen zu belassen. Die Bruttopreise können sich dennoch "
"ändern, wenn sie durch Errechnung von einem gerundeten Nettopreis nicht "
"erreichbar sind."
#: pretix/control/forms/event.py:961
msgid "Generate invoices for Sales channels"
@@ -21284,10 +21278,6 @@ msgid ""
"optionally contain additional rules that depend on the customer's country "
"and type."
msgstr ""
"Steuer-Regeln definieren unterschiedliche Besteuerungsszenarien, die dann "
"den verschiedenen Produkten zugewiesen werden können. Jede Steuer-Regel "
"enthält einen Standard-Steuersatz und kann optional zusätzliche Regeln "
"enthalten, die auf die Art und Herkunft des Kunden Bezug nehmen."
#: pretix/control/templates/pretixcontrol/event/tax.html:21
msgid "You haven't created any tax rules yet."
@@ -21314,11 +21304,13 @@ msgid "Make default"
msgstr "Zum Standard machen"
#: pretix/control/templates/pretixcontrol/event/tax.html:67
#, python-format
#, fuzzy, python-format
#| msgid "%(count)s event"
#| msgid_plural "%(count)s events"
msgid "%(count)s product"
msgid_plural "%(count)s products"
msgstr[0] "%(count)s Produkt"
msgstr[1] "%(count)s Produkte"
msgstr[0] "%(count)s Veranstaltung"
msgstr[1] "%(count)s Veranstaltungen"
#: pretix/control/templates/pretixcontrol/event/tax.html:75
#, python-format
@@ -21331,12 +21323,16 @@ msgid "excl. %(rate)s %%"
msgstr "zzgl. %(rate)s %%"
#: pretix/control/templates/pretixcontrol/event/tax.html:80
#, fuzzy
#| msgid "Custom rules"
msgid "with custom rules"
msgstr "mit eigenen Regeln"
msgstr "Eigene Regeln"
#: pretix/control/templates/pretixcontrol/event/tax.html:110
#, fuzzy
#| msgid "Base settings"
msgid "Tax settings"
msgstr "Steuer-Einstellungen"
msgstr "Grundeinstellungen"
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:4
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:6
@@ -24153,7 +24149,7 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/order/transactions.html:73
#, python-format
msgid "incl. %(amount)s rounding correction"
msgstr "inkl. %(amount)s Rundungskorrektur"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:5
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:7

View File

@@ -362,9 +362,6 @@ Reverse-Proxy
Revisionssicherheit
Revolut
Revolut-App
Rundungsabweichungen
Rundungskorrektur
Rundungsverhalten
rückabgewickelt
Sa
Sammlungsstücken

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-30 10:55+0000\n"
"PO-Revision-Date: 2025-10-30 20:00+0000\n"
"PO-Revision-Date: 2025-10-29 09:24+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
"pretix/pretix/de_Informal/>\n"
@@ -9651,15 +9651,15 @@ msgstr "Der Gutschein wurde an {recipient} verschickt."
#: pretix/base/settings.py:81
msgid "Compute taxes for every line individually"
msgstr "Berechne Steuern für jede Position einzeln"
msgstr ""
#: pretix/base/settings.py:82
msgid "Compute taxes based on net total"
msgstr "Berechne Steuern auf Basis der Nettosumme"
msgstr ""
#: pretix/base/settings.py:83
msgid "Compute taxes based on net total with stable gross prices"
msgstr "Berechne Steuern auf Basis der Nettosumme mit konstanten Bruttopreisen"
msgstr ""
#: pretix/base/settings.py:133
msgid "Allow usage of restricted plugins"
@@ -9749,8 +9749,13 @@ msgid "Add-on products will not be counted."
msgstr "Zusatzprodukte werden nicht mitgezählt."
#: pretix/base/settings.py:334
#, fuzzy
#| msgid ""
#| "Show net prices instead of gross prices in the product list (not "
#| "recommended!)"
msgid "Show net prices instead of gross prices in the product list"
msgstr "Zeigen Nettopreise statt Bruttopreisen in der Produktliste"
msgstr ""
"Zeige Netto- statt Bruttopreisen in den Produktlisten (nicht empfohlen)"
#: pretix/base/settings.py:335
msgid ""
@@ -9867,8 +9872,10 @@ msgid "Require a phone number per order"
msgstr "Telefonnummer pro Bestellung erfordern"
#: pretix/base/settings.py:481
#, fuzzy
#| msgid "including all taxes"
msgid "Rounding of taxes"
msgstr "Rundung der Steuern"
msgstr "inklusive aller Steuern"
#: pretix/base/settings.py:485
msgid ""
@@ -9876,10 +9883,6 @@ msgid ""
"for tax reporting, you need to make sure to account for possible rounding "
"differences if your external system rounds differently than pretix."
msgstr ""
"Bitte beachte, dass bei der Übertragung der Verkaufsdaten in ein externes "
"Buchhaltungssystem darauf geachtet werden muss, dass potentielle "
"Rundungsabweichungen behandelt werden, wenn das externe System anders rundet "
"als pretix."
#: pretix/base/settings.py:500
msgid "Ask for invoice address"
@@ -14010,24 +14013,31 @@ msgstr ""
"Ausstellung ablaufen."
#: pretix/control/forms/event.py:806
#, fuzzy
#| msgid "including all taxes"
msgid "Prices including tax"
msgstr "Preis inklusive Steuern"
msgstr "inklusive aller Steuern"
#: pretix/control/forms/event.py:807
msgid "Recommended if you sell tickets at least partly to consumers."
msgstr "Empfohlen, wenn mindestens teilweise an Verbraucher verkauft wird."
msgstr ""
#: pretix/control/forms/event.py:811
#, fuzzy
#| msgctxt "reporting_timeframe"
#| msgid "All future (excluding today)"
msgid "Prices excluding tax"
msgstr "Preise exklusive Steuern"
msgstr "Zukunft (ab morgen)"
#: pretix/control/forms/event.py:812
msgid "Recommended only if you sell tickets primarily to business customers."
msgstr "Empfohlen, wenn primär an Geschäftskunden verkauft wird."
msgstr ""
#: pretix/control/forms/event.py:848
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Prices shown to customer"
msgstr "Preisanzeige für Kunden"
msgstr "Wunschdatum des Kunden"
#: pretix/control/forms/event.py:852
msgid ""
@@ -14036,10 +14046,6 @@ msgid ""
"product, the total tax amount can differ from when it would be computed from "
"the order total."
msgstr ""
"Empfohlen, wenn keine E-Rechnungen benötigt werden. Jedes Produkt wird zum "
"beworbenen Netto- und Bruttopreis verkauft. Im Fall von Bestellungen mit "
"mehreren Produkten kann die Gesamt-Steuersumme höher oder niedriger sein als "
"die, die sich aus der Bestellsumme berechnen würde."
#: pretix/control/forms/event.py:857
msgid ""
@@ -14048,11 +14054,6 @@ msgid ""
"may be changed to ensure correct rounding, while the net prices will be kept "
"as configured. This may cause the actual payment amount to differ."
msgstr ""
"Empfohlen für E-Rechnungen, wenn primär an Geschäftskunden verkauft wird und "
"Kunden Nettopreise angezeigt werden. Der Bruttopreis einzelner Produkte kann "
"sich automatisch ändern, um ein korrektes Rundungsverhalten sicherzustellen, "
"während die Nettopreise immer den eingestellten Preisen entsprechen. Der "
"resultierende Zahlungsbetrag kann durch die Rundung abweichen."
#: pretix/control/forms/event.py:863
msgid ""
@@ -14062,13 +14063,6 @@ msgid ""
"configured whenever possible. Gross prices may still change if they are "
"impossible to derive from a rounded net price."
msgstr ""
"Empfohlen für E-Rechnungen, wenn primär an Verbraucher verkauft wird und "
"Kunden Bruttopreise angezeigt werden. Der Netto- oder Bruttopreis einzelner "
"Produkte kann sich automatisch ändern, um ein korrektes Rundungsverhalten "
"sicherzustellen. Dabei versucht das System, die Bruttopreise möglichst bei "
"den eingestellten Preisen zu belassen. Die Bruttopreise können sich dennoch "
"ändern, wenn sie durch Errechnung von einem gerundeten Nettopreis nicht "
"erreichbar sind."
#: pretix/control/forms/event.py:961
msgid "Generate invoices for Sales channels"
@@ -21254,10 +21248,6 @@ msgid ""
"optionally contain additional rules that depend on the customer's country "
"and type."
msgstr ""
"Steuer-Regeln definieren unterschiedliche Besteuerungsszenarien, die dann "
"den verschiedenen Produkten zugewiesen werden können. Jede Steuer-Regel "
"enthält einen Standard-Steuersatz und kann optional zusätzliche Regeln "
"enthalten, die auf die Art und Herkunft des Kunden Bezug nehmen."
#: pretix/control/templates/pretixcontrol/event/tax.html:21
msgid "You haven't created any tax rules yet."
@@ -21284,11 +21274,13 @@ msgid "Make default"
msgstr "Zum Standard machen"
#: pretix/control/templates/pretixcontrol/event/tax.html:67
#, python-format
#, fuzzy, python-format
#| msgid "%(count)s event"
#| msgid_plural "%(count)s events"
msgid "%(count)s product"
msgid_plural "%(count)s products"
msgstr[0] "%(count)s Produkt"
msgstr[1] "%(count)s Produkte"
msgstr[0] "%(count)s Veranstaltung"
msgstr[1] "%(count)s Veranstaltungen"
#: pretix/control/templates/pretixcontrol/event/tax.html:75
#, python-format
@@ -21301,12 +21293,16 @@ msgid "excl. %(rate)s %%"
msgstr "zzgl. %(rate)s %%"
#: pretix/control/templates/pretixcontrol/event/tax.html:80
#, fuzzy
#| msgid "Custom rules"
msgid "with custom rules"
msgstr "mit eigenen Regeln"
msgstr "Eigene Regeln"
#: pretix/control/templates/pretixcontrol/event/tax.html:110
#, fuzzy
#| msgid "Base settings"
msgid "Tax settings"
msgstr "Steuer-Einstellungen"
msgstr "Grundeinstellungen"
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:4
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:6
@@ -24120,7 +24116,7 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/order/transactions.html:73
#, python-format
msgid "incl. %(amount)s rounding correction"
msgstr "inkl. %(amount)s Rundungskorrektur"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:5
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:7

View File

@@ -362,9 +362,6 @@ Reverse-Proxy
Revisionssicherheit
Revolut
Revolut-App
Rundungsabweichungen
Rundungskorrektur
Rundungsverhalten
rückabgewickelt
Sa
Sammlungsstücken

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-30 10:55+0000\n"
"PO-Revision-Date: 2025-11-04 10:25+0000\n"
"PO-Revision-Date: 2025-10-22 16:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix/"
"es/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.14\n"
"X-Generator: Weblate 5.13.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -8346,8 +8346,10 @@ msgid "Event canceled"
msgstr "Evento cancelado"
#: pretix/base/services/cancelevent.py:392
#, fuzzy
#| msgid "Create configuration"
msgid "Bulk-refund confirmation"
msgstr "Confirmación de reembolso masivo"
msgstr "Crear configuración"
#: pretix/base/services/cart.py:102 pretix/base/services/modelimport.py:247
#: pretix/base/services/orders.py:155
@@ -9653,16 +9655,15 @@ msgstr "El vale de compra ha sido enviado a {recipient}."
#: pretix/base/settings.py:81
msgid "Compute taxes for every line individually"
msgstr "Calcular los impuestos para cada línea individualmente"
msgstr ""
#: pretix/base/settings.py:82
msgid "Compute taxes based on net total"
msgstr "Calcular los impuestos basándose en el total neto"
msgstr ""
#: pretix/base/settings.py:83
msgid "Compute taxes based on net total with stable gross prices"
msgstr ""
"Calcular los impuestos basándose en el total neto con precios brutos estables"
#: pretix/base/settings.py:133
msgid "Allow usage of restricted plugins"
@@ -9754,9 +9755,14 @@ msgid "Add-on products will not be counted."
msgstr "Los productos adicionales no se contarán."
#: pretix/base/settings.py:334
#, fuzzy
#| msgid ""
#| "Show net prices instead of gross prices in the product list (not "
#| "recommended!)"
msgid "Show net prices instead of gross prices in the product list"
msgstr ""
"Mostrar precios netos en lugar de precios brutos en la lista de productos"
"Mostrar precios netos en lugar de precios brutos en la lista de productos "
"(¡no recomendado!)"
#: pretix/base/settings.py:335
msgid ""
@@ -9877,8 +9883,10 @@ msgid "Require a phone number per order"
msgstr "Requerir un número de teléfono por pedido"
#: pretix/base/settings.py:481
#, fuzzy
#| msgid "including all taxes"
msgid "Rounding of taxes"
msgstr "Redondeo de impuestos"
msgstr "impuestos incluidos"
#: pretix/base/settings.py:485
msgid ""
@@ -9886,10 +9894,6 @@ msgid ""
"for tax reporting, you need to make sure to account for possible rounding "
"differences if your external system rounds differently than pretix."
msgstr ""
"Tenga en cuenta que si transfiere sus datos de ventas desde pretix a un "
"sistema externo para la declaración de impuestos, debe asegurarse de tener "
"en cuenta las posibles diferencias de redondeo si su sistema externo "
"redondea de forma diferente a pretix."
#: pretix/base/settings.py:500
msgid "Ask for invoice address"
@@ -13160,20 +13164,18 @@ msgstr ""
msgid ""
"You have requested us to cancel an event which includes a larger bulk-refund:"
msgstr ""
"Nos ha solicitado cancelar un evento que incluye un reembolso masivo de "
"mayor importe:"
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:6
#, fuzzy
#| msgid "Initiate a refund of %(amount)s"
msgid "Estimated refund amount"
msgstr "Importe estimado del reembolso"
msgstr "Iniciar un reembolso de %(amount)s"
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:8
msgid ""
"Please confirm that you want to proceed by coping the following confirmation "
"code into the cancellation form:"
msgstr ""
"Confirme que desea continuar copiando el siguiente código de confirmación en "
"el formulario de cancelación:"
#: pretix/base/templates/pretixbase/email/email_footer.html:3
#, python-format
@@ -14015,25 +14017,31 @@ msgstr ""
"año en el que se emite la tarjeta de regalo."
#: pretix/control/forms/event.py:806
#, fuzzy
#| msgid "including all taxes"
msgid "Prices including tax"
msgstr "Precios con impuestos incluidos"
msgstr "impuestos incluidos"
#: pretix/control/forms/event.py:807
msgid "Recommended if you sell tickets at least partly to consumers."
msgstr "Recomendado si se venden entradas, al menos en parte, a consumidores."
msgstr ""
#: pretix/control/forms/event.py:811
#, fuzzy
#| msgctxt "reporting_timeframe"
#| msgid "All future (excluding today)"
msgid "Prices excluding tax"
msgstr "Precios sin impuestos"
msgstr "Todo el futuro (excepto hoy)"
#: pretix/control/forms/event.py:812
msgid "Recommended only if you sell tickets primarily to business customers."
msgstr ""
"Recomendado solo si vende entradas principalmente a clientes empresariales."
#: pretix/control/forms/event.py:848
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Prices shown to customer"
msgstr "Precios mostrados a los clientes"
msgstr "Fecha elegida por el cliente"
#: pretix/control/forms/event.py:852
msgid ""
@@ -14042,10 +14050,6 @@ msgid ""
"product, the total tax amount can differ from when it would be computed from "
"the order total."
msgstr ""
"Recomendado cuando no se requiere facturación electrónica. Cada producto se "
"venderá con el precio neto y bruto anunciado. Sin embargo, en pedidos de más "
"de un producto, el importe total de los impuestos puede diferir del que se "
"calcularía a partir del total del pedido."
#: pretix/control/forms/event.py:857
msgid ""
@@ -14054,12 +14058,6 @@ msgid ""
"may be changed to ensure correct rounding, while the net prices will be kept "
"as configured. This may cause the actual payment amount to differ."
msgstr ""
"Recomendado para la facturación electrónica cuando se vende principalmente a "
"clientes empresariales y se muestran los precios a los clientes sin "
"impuestos. El precio bruto de algunos productos puede modificarse para "
"garantizar un redondeo correcto, mientras que los precios netos se "
"mantendrán tal y como están configurados. Esto puede provocar que el importe "
"real del pago sea diferente."
#: pretix/control/forms/event.py:863
msgid ""
@@ -14069,12 +14067,6 @@ msgid ""
"configured whenever possible. Gross prices may still change if they are "
"impossible to derive from a rounded net price."
msgstr ""
"Recomendado para la facturación electrónica cuando se vende principalmente a "
"consumidores. El precio bruto o neto de algunos productos puede modificarse "
"automáticamente para garantizar el redondeo correcto del total del pedido. "
"El sistema intenta mantener los precios brutos tal y como se han configurado "
"siempre que sea posible. Los precios brutos pueden seguir cambiando si no es "
"posible obtenerlos a partir de un precio neto redondeado."
#: pretix/control/forms/event.py:961
msgid "Generate invoices for Sales channels"
@@ -16193,7 +16185,7 @@ msgstr "Confirme que desea cancelar TODAS las fechas de esta serie de eventos."
#: pretix/control/forms/orders.py:1037
msgid "I understand that this is not reversible and want to continue"
msgstr "Entiendo que esto no es reversible y deseo continuar"
msgstr ""
#: pretix/control/forms/orders.py:1041
#: pretix/control/templates/pretixcontrol/shredder/download.html:53
@@ -16204,12 +16196,12 @@ msgstr "Código de confirmación"
msgid ""
"We have just emailed you a confirmation code to enter to confirm this action"
msgstr ""
"Acabamos de enviarle por correo electrónico un código de confirmación que "
"deberá introducir para confirmar esta acción"
#: pretix/control/forms/orders.py:1055
#, fuzzy
#| msgid "The confirm code you entered was incorrect."
msgid "The confirmation code is incorrect."
msgstr "El código de confirmación es incorrecto."
msgstr "El código de confirmación que introdujo era incorrecto."
#: pretix/control/forms/organizer.py:93
msgid "This slug is already in use. Please choose a different one."
@@ -21276,10 +21268,6 @@ msgid ""
"optionally contain additional rules that depend on the customer's country "
"and type."
msgstr ""
"Las normas fiscales definen diferentes escenarios fiscales que luego se "
"pueden asignar a los productos individuales. Cada norma fiscal contiene un "
"tipo impositivo predeterminado y, opcionalmente, puede contener normas "
"adicionales que dependen del país y el tipo de cliente."
#: pretix/control/templates/pretixcontrol/event/tax.html:21
msgid "You haven't created any tax rules yet."
@@ -21306,11 +21294,13 @@ msgid "Make default"
msgstr "Establecer por defecto"
#: pretix/control/templates/pretixcontrol/event/tax.html:67
#, python-format
#, fuzzy, python-format
#| msgid "%(count)s event"
#| msgid_plural "%(count)s events"
msgid "%(count)s product"
msgid_plural "%(count)s products"
msgstr[0] "%(count)s producto"
msgstr[1] "%(count)s productos"
msgstr[0] "%(count)s elemento"
msgstr[1] "%(count)s elementos"
#: pretix/control/templates/pretixcontrol/event/tax.html:75
#, python-format
@@ -21323,12 +21313,16 @@ msgid "excl. %(rate)s %%"
msgstr "excluido %(rate)s %%"
#: pretix/control/templates/pretixcontrol/event/tax.html:80
#, fuzzy
#| msgid "Custom rules"
msgid "with custom rules"
msgstr "con reglas personalizadas"
msgstr "Reglas personalizadas"
#: pretix/control/templates/pretixcontrol/event/tax.html:110
#, fuzzy
#| msgid "Base settings"
msgid "Tax settings"
msgstr "Configuración de impuestos"
msgstr "Ajustes básicos"
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:4
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:6
@@ -24147,7 +24141,7 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/order/transactions.html:73
#, python-format
msgid "incl. %(amount)s rounding correction"
msgstr "incl. %(amount)s corrección por redondeo"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:5
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:7
@@ -24253,77 +24247,84 @@ msgstr ""
"los que estén en la lista de espera recibirán varios correos electrónicos."
#: pretix/control/templates/pretixcontrol/orders/cancel.html:84
#, fuzzy
#| msgid "Refund amount"
msgid "Preview refund amount"
msgstr "Previsualizar el importe del reembolso"
msgstr "Importe del reembolso"
#: pretix/control/templates/pretixcontrol/orders/cancel.html:88
msgid "Cancel all orders"
msgstr "Cancelar todos los pedidos"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:13
#, fuzzy
#| msgid "If you contact us, please send us the following code:"
msgid "If you proceed, the system will do the following:"
msgstr "Si continúa, el sistema hará lo siguiente:"
msgstr ""
"Si se pone en contacto con nosotros, por favor envíenos el siguiente código:"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:19
#, python-format
msgid "%(count)s order will be canceled fully"
msgid_plural "%(count)s orders will be canceled fully"
msgstr[0] "%(count)s pedido se cancelará por completo"
msgstr[1] "%(count)s pedidos se cancelarán por completo"
msgstr[0] ""
msgstr[1] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:26
#, python-format
msgid "%(count)s order will be canceled partially"
msgid_plural "%(count)s orders will be canceled partially"
msgstr[0] "%(count)s pedido se cancelará parcialmente"
msgstr[1] "%(count)s pedidos se cancelarán parcialmente"
msgstr[0] ""
msgstr[1] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:36
#, python-format
msgid "%(amount)s are eligible for refunds."
msgstr "%(amount)s son reembolsables."
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:40
msgid ""
"The system will attempt to refund the money automatically if supported by "
"the payment method."
msgstr ""
"El sistema intentará reembolsar el dinero automáticamente si el método de "
"pago lo permite."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:42
msgid "The system will create manual refunds that you need to execute."
msgstr "El sistema creará reembolsos manuales que deberá ejecutar."
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:44
#, fuzzy
#| msgid "Text (if order will not expire automatically)"
msgid "Refunds will not happen automatically."
msgstr "Los reembolsos no se realizarán automáticamente."
msgstr "Texto (si el pedido no caducará automáticamente)"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:52
#, fuzzy
#| msgid "Send information via email"
msgid "Inform all customers via email."
msgstr "Informar a todos los clientes por correo electrónico."
msgstr "Enviar información por correo electrónico"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:57
msgid "Inform all waiting list contacts via email."
msgstr ""
"Informar a todos los contactos de la lista de espera por correo electrónico."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:62
msgid ""
"These numbers are estimates and may change if the data in your event "
"recently changed."
msgstr ""
"Estas cifras son estimaciones y pueden variar si los datos del evento han "
"cambiado recientemente."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:76
#, python-format
#, fuzzy, python-format
#| msgid "Initiate a refund of %(amount)s"
msgid "Proceed and refund approx. %(amount)s"
msgstr "Proseguir y reembolsar aprox. %(amount)s"
msgstr "Iniciar un reembolso de %(amount)s"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:80
#, fuzzy
#| msgid "Yes, cancel order"
msgid "Proceed and cancel orders"
msgstr "Proceder y cancelar pedidos"
msgstr "Sí, cancelar pedido"
#: pretix/control/templates/pretixcontrol/orders/export.html:5
#: pretix/control/templates/pretixcontrol/orders/export.html:8

View File

@@ -4,7 +4,7 @@ msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-30 10:55+0000\n"
"PO-Revision-Date: 2025-11-04 10:25+0000\n"
"PO-Revision-Date: 2025-10-22 16:00+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
">\n"
@@ -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.14\n"
"X-Generator: Weblate 5.13.3\n"
#: pretix/_base_settings.py:87
msgid "English"
@@ -8397,8 +8397,10 @@ msgid "Event canceled"
msgstr "Événement annulé"
#: pretix/base/services/cancelevent.py:392
#, fuzzy
#| msgid "Create configuration"
msgid "Bulk-refund confirmation"
msgstr "Confirmation de remboursement en bloc"
msgstr "Créer une configuration"
#: pretix/base/services/cart.py:102 pretix/base/services/modelimport.py:247
#: pretix/base/services/orders.py:155
@@ -9718,15 +9720,15 @@ msgstr "Le bon a été envoyé à {recipient}."
#: pretix/base/settings.py:81
msgid "Compute taxes for every line individually"
msgstr "Calculer les taxes individuellement pour chaque ligne"
msgstr ""
#: pretix/base/settings.py:82
msgid "Compute taxes based on net total"
msgstr "Calculer les taxes sur la base du total net"
msgstr ""
#: pretix/base/settings.py:83
msgid "Compute taxes based on net total with stable gross prices"
msgstr "Calculer les taxes sur la base du total net avec des prix bruts stables"
msgstr ""
#: pretix/base/settings.py:133
msgid "Allow usage of restricted plugins"
@@ -9819,9 +9821,14 @@ msgid "Add-on products will not be counted."
msgstr "Les Add-Ons e sont pas comptabilisés."
#: pretix/base/settings.py:334
#, fuzzy
#| msgid ""
#| "Show net prices instead of gross prices in the product list (not "
#| "recommended!)"
msgid "Show net prices instead of gross prices in the product list"
msgstr ""
"Afficher les prix nets au lieu des prix bruts dans la liste des produits"
"Afficher les prix nets au lieu des prix bruts dans la liste de produits (pas "
"recommandé!)"
#: pretix/base/settings.py:335
msgid ""
@@ -9940,8 +9947,10 @@ msgid "Require a phone number per order"
msgstr "Exiger un numéro de téléphone par commande"
#: pretix/base/settings.py:481
#, fuzzy
#| msgid "including all taxes"
msgid "Rounding of taxes"
msgstr "Arrondi des taxes"
msgstr "toutes taxes comprises"
#: pretix/base/settings.py:485
msgid ""
@@ -9949,10 +9958,6 @@ msgid ""
"for tax reporting, you need to make sure to account for possible rounding "
"differences if your external system rounds differently than pretix."
msgstr ""
"Veuillez noter que si vous transférez vos données de vente depuis pretix "
"vers un système externe à des fins de déclaration fiscale, vous devez tenir "
"compte des éventuelles différences d'arrondi si votre système externe "
"arrondit différemment de pretix."
#: pretix/base/settings.py:500
msgid "Ask for invoice address"
@@ -13285,20 +13290,18 @@ msgstr ""
msgid ""
"You have requested us to cancel an event which includes a larger bulk-refund:"
msgstr ""
"Vous nous avez demandé d'annuler un événement qui implique un remboursement "
"groupé important :"
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:6
#, fuzzy
#| msgid "Initiate a refund of %(amount)s"
msgid "Estimated refund amount"
msgstr "Montant estimé du remboursement"
msgstr "Initier un remboursement de %(amount)s"
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:8
msgid ""
"Please confirm that you want to proceed by coping the following confirmation "
"code into the cancellation form:"
msgstr ""
"Veuillez confirmer que vous souhaitez poursuivre en copiant le code de "
"confirmation suivant dans le formulaire d'annulation :"
#: pretix/base/templates/pretixbase/email/email_footer.html:3
#, python-format
@@ -14148,27 +14151,31 @@ msgstr ""
"plus lannée démission de la carte-cadeau."
#: pretix/control/forms/event.py:806
#, fuzzy
#| msgid "including all taxes"
msgid "Prices including tax"
msgstr "Prix TTC"
msgstr "toutes taxes comprises"
#: pretix/control/forms/event.py:807
msgid "Recommended if you sell tickets at least partly to consumers."
msgstr ""
"Recommandé si vous vendez des billets au moins en partie à des consommateurs."
#: pretix/control/forms/event.py:811
#, fuzzy
#| msgctxt "reporting_timeframe"
#| msgid "All future (excluding today)"
msgid "Prices excluding tax"
msgstr "Prix hors taxes"
msgstr "Tout futur (sauf aujourdhui)"
#: pretix/control/forms/event.py:812
msgid "Recommended only if you sell tickets primarily to business customers."
msgstr ""
"Recommandé uniquement si vous vendez principalement des billets à des "
"clients professionnels."
#: pretix/control/forms/event.py:848
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Prices shown to customer"
msgstr "Prix indiqués aux clients"
msgstr "Date choisie par le client"
#: pretix/control/forms/event.py:852
msgid ""
@@ -14177,11 +14184,6 @@ msgid ""
"product, the total tax amount can differ from when it would be computed from "
"the order total."
msgstr ""
"Recommandé lorsque la facturation électronique n'est pas requise. Chaque "
"produit sera vendu au prix net et brut annoncé. Cependant, dans le cas de "
"commandes comprenant plusieurs produits, le montant total des taxes peut "
"différer de celui qui serait calculé à partir du montant total de la "
"commande."
#: pretix/control/forms/event.py:857
msgid ""
@@ -14190,12 +14192,6 @@ msgid ""
"may be changed to ensure correct rounding, while the net prices will be kept "
"as configured. This may cause the actual payment amount to differ."
msgstr ""
"Recommandé pour la facturation électronique lorsque vous vendez "
"principalement à des clients professionnels et affichez les prix hors taxes "
"à vos clients. Le prix brut de certains produits peut être modifié afin "
"d'assurer un arrondi correct, tandis que les prix nets resteront tels qu'ils "
"ont été configurés. Cela peut entraîner une différence entre le montant réel "
"du paiement et le montant indiqué."
#: pretix/control/forms/event.py:863
msgid ""
@@ -14205,13 +14201,6 @@ msgid ""
"configured whenever possible. Gross prices may still change if they are "
"impossible to derive from a rounded net price."
msgstr ""
"Recommandé pour la facturation électronique lorsque vous vendez "
"principalement à des consommateurs. Le prix brut ou net de certains produits "
"peut être modifié automatiquement afin d'assurer un arrondi correct du total "
"de la commande. Le système tente de conserver les prix bruts tels qu'ils ont "
"été configurés dans la mesure du possible. Les prix bruts peuvent toutefois "
"être modifiés s'il est impossible de les calculer à partir d'un prix net "
"arrondi."
#: pretix/control/forms/event.py:961
msgid "Generate invoices for Sales channels"
@@ -16343,7 +16332,6 @@ msgstr ""
#: pretix/control/forms/orders.py:1037
msgid "I understand that this is not reversible and want to continue"
msgstr ""
"Je comprends que cette opération est irréversible et je souhaite continuer"
#: pretix/control/forms/orders.py:1041
#: pretix/control/templates/pretixcontrol/shredder/download.html:53
@@ -16354,12 +16342,12 @@ msgstr "Code de confirmation"
msgid ""
"We have just emailed you a confirmation code to enter to confirm this action"
msgstr ""
"Nous venons de vous envoyer par e-mail un code de confirmation à saisir pour "
"confirmer cette action"
#: pretix/control/forms/orders.py:1055
#, fuzzy
#| msgid "The confirm code you entered was incorrect."
msgid "The confirmation code is incorrect."
msgstr "Le code de confirmation est incorrect."
msgstr "Le code de confirmation que vous avez entré était incorrect."
#: pretix/control/forms/organizer.py:93
msgid "This slug is already in use. Please choose a different one."
@@ -21431,10 +21419,6 @@ msgid ""
"optionally contain additional rules that depend on the customer's country "
"and type."
msgstr ""
"Les règles fiscales définissent différents scénarios d'imposition qui "
"peuvent ensuite être attribués à chaque produit. Chaque règle fiscale "
"contient un taux d'imposition par défaut et peut éventuellement contenir des "
"règles supplémentaires qui dépendent du pays et du type de client."
#: pretix/control/templates/pretixcontrol/event/tax.html:21
msgid "You haven't created any tax rules yet."
@@ -21461,11 +21445,13 @@ msgid "Make default"
msgstr "Définir par défaut"
#: pretix/control/templates/pretixcontrol/event/tax.html:67
#, python-format
#, fuzzy, python-format
#| msgid "%(count)s event"
#| msgid_plural "%(count)s events"
msgid "%(count)s product"
msgid_plural "%(count)s products"
msgstr[0] "%(count)s produit"
msgstr[1] "%(count)s produits"
msgstr[0] "%(count)s élement"
msgstr[1] "%(count)s élements"
#: pretix/control/templates/pretixcontrol/event/tax.html:75
#, python-format
@@ -21478,12 +21464,16 @@ msgid "excl. %(rate)s %%"
msgstr "hors %(rate)s %%"
#: pretix/control/templates/pretixcontrol/event/tax.html:80
#, fuzzy
#| msgid "Custom rules"
msgid "with custom rules"
msgstr "avec des règles personnalisées"
msgstr "Règles personnalisées"
#: pretix/control/templates/pretixcontrol/event/tax.html:110
#, fuzzy
#| msgid "Base settings"
msgid "Tax settings"
msgstr "Paramètres relatifs aux taxes"
msgstr "Réglages de base"
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:4
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:6
@@ -24324,7 +24314,7 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/order/transactions.html:73
#, python-format
msgid "incl. %(amount)s rounding correction"
msgstr "y compris %(amount)s de correction d'arrondi"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:5
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:7
@@ -24435,77 +24425,83 @@ msgstr ""
"plusieurs courriels."
#: pretix/control/templates/pretixcontrol/orders/cancel.html:84
#, fuzzy
#| msgid "Refund amount"
msgid "Preview refund amount"
msgstr "Prévisualiser le montant du remboursement"
msgstr "Montant du remboursement"
#: pretix/control/templates/pretixcontrol/orders/cancel.html:88
msgid "Cancel all orders"
msgstr "Annuler toutes les commandes"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:13
#, fuzzy
#| msgid "If you contact us, please send us the following code:"
msgid "If you proceed, the system will do the following:"
msgstr "Si vous continuez, le système effectuera les opérations suivantes :"
msgstr "Si vous nous contactez, veuillez nous envoyer le code suivant:"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:19
#, python-format
msgid "%(count)s order will be canceled fully"
msgid_plural "%(count)s orders will be canceled fully"
msgstr[0] "%(count)s commande sera totalement annulée"
msgstr[1] "%(count)s commandes seront totalement annulées"
msgstr[0] ""
msgstr[1] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:26
#, python-format
msgid "%(count)s order will be canceled partially"
msgid_plural "%(count)s orders will be canceled partially"
msgstr[0] "%(count)s commande sera partiellement annulé"
msgstr[1] "%(count)s commandes seront partiellement annulées"
msgstr[0] ""
msgstr[1] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:36
#, python-format
msgid "%(amount)s are eligible for refunds."
msgstr "%(amount)s sont susceptibles d'être remboursés."
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:40
msgid ""
"The system will attempt to refund the money automatically if supported by "
"the payment method."
msgstr ""
"Le système tentera de rembourser automatiquement l'argent si le mode de "
"paiement le permet."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:42
msgid "The system will create manual refunds that you need to execute."
msgstr "Le système créera des remboursements manuels que vous devrez exécuter."
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:44
#, fuzzy
#| msgid "Text (if order will not expire automatically)"
msgid "Refunds will not happen automatically."
msgstr "Les remboursements ne se feront pas automatiquement."
msgstr "Texte (si la commande nexpire pas automatiquement)"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:52
#, fuzzy
#| msgid "Send information via email"
msgid "Inform all customers via email."
msgstr "Informez tous les clients par e-mail."
msgstr "Envoyer des informations par e-mail"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:57
msgid "Inform all waiting list contacts via email."
msgstr ""
"Informez toutes les personnes inscrites sur la liste d'attente par e-mail."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:62
msgid ""
"These numbers are estimates and may change if the data in your event "
"recently changed."
msgstr ""
"Ces chiffres sont des estimations et peuvent changer si les données "
"relatives à votre événement ont récemment été modifiées."
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:76
#, python-format
#, fuzzy, python-format
#| msgid "Initiate a refund of %(amount)s"
msgid "Proceed and refund approx. %(amount)s"
msgstr "Poursuivre et rembourser environ %(amount)s"
msgstr "Initier un remboursement de %(amount)s"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:80
#, fuzzy
#| msgid "Yes, cancel order"
msgid "Proceed and cancel orders"
msgstr "Poursuivre et annuler les commandes"
msgstr "Oui, annuler la commande"
#: pretix/control/templates/pretixcontrol/orders/export.html:5
#: pretix/control/templates/pretixcontrol/orders/export.html:8

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-30 10:55+0000\n"
"PO-Revision-Date: 2025-11-04 10:25+0000\n"
"PO-Revision-Date: 2025-10-27 12:00+0000\n"
"Last-Translator: Yasunobu YesNo Kawaguchi <kawaguti@gmail.com>\n"
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/pretix/"
"ja/>\n"
@@ -8190,8 +8190,10 @@ msgid "Event canceled"
msgstr "イベントがキャンセルされました"
#: pretix/base/services/cancelevent.py:392
#, fuzzy
#| msgid "Add confirmation text"
msgid "Bulk-refund confirmation"
msgstr "一括払い戻しの確認"
msgstr "確認テキストを追加"
#: pretix/base/services/cart.py:102 pretix/base/services/modelimport.py:247
#: pretix/base/services/orders.py:155
@@ -9429,15 +9431,15 @@ msgstr "バウチャーは、{recipient}あてに送信されました。"
#: pretix/base/settings.py:81
msgid "Compute taxes for every line individually"
msgstr "各行ごとに税額を計算する"
msgstr ""
#: pretix/base/settings.py:82
msgid "Compute taxes based on net total"
msgstr "税抜合計に基づいて税額を計算する"
msgstr ""
#: pretix/base/settings.py:83
msgid "Compute taxes based on net total with stable gross prices"
msgstr "税込価格を固定して税抜合計に基づいて税額を計算する"
msgstr ""
#: pretix/base/settings.py:133
msgid "Allow usage of restricted plugins"
@@ -9525,8 +9527,12 @@ msgid "Add-on products will not be counted."
msgstr "アドオン製品はカウントされません。"
#: pretix/base/settings.py:334
#, fuzzy
#| msgid ""
#| "Show net prices instead of gross prices in the product list (not "
#| "recommended!)"
msgid "Show net prices instead of gross prices in the product list"
msgstr "製品リストに税込価格ではなく税抜価格を表示する"
msgstr "製品リストには、総額ではなく純額を表示してください(お勧めしません!)"
#: pretix/base/settings.py:335
msgid ""
@@ -9640,8 +9646,10 @@ msgid "Require a phone number per order"
msgstr "1注文につき1つの電話番号が必要"
#: pretix/base/settings.py:481
#, fuzzy
#| msgid "including all taxes"
msgid "Rounding of taxes"
msgstr "税額の端数処理"
msgstr "すべての税金を含めて"
#: pretix/base/settings.py:485
msgid ""
@@ -9649,9 +9657,6 @@ msgid ""
"for tax reporting, you need to make sure to account for possible rounding "
"differences if your external system rounds differently than pretix."
msgstr ""
"pretixから外部システムに販売データを転送して税務申告を行う場合、外部システム"
"の端数処理がpretixと異なる場合は、端数処理の差異を考慮する必要があることに注"
"意してください。"
#: pretix/base/settings.py:500
msgid "Ask for invoice address"
@@ -12786,18 +12791,19 @@ msgstr "数分以上かかる場合は、このページを更新するか、お
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:2
msgid ""
"You have requested us to cancel an event which includes a larger bulk-refund:"
msgstr "大量の払い戻しを伴うイベントのキャンセルをリクエストされました:"
msgstr ""
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:6
#, fuzzy
#| msgid "Initiate a refund of %(amount)s"
msgid "Estimated refund amount"
msgstr "推定払い戻し金額"
msgstr "%(amount)sの払い戻しを開始する"
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:8
msgid ""
"Please confirm that you want to proceed by coping the following confirmation "
"code into the cancellation form:"
msgstr "以下の確認コードをキャンセルフォームにコピーして、続行することを確認してくだ"
"さい:"
msgstr ""
#: pretix/base/templates/pretixbase/email/email_footer.html:3
#, python-format
@@ -13618,24 +13624,31 @@ msgid ""
msgstr "ギフトカードの有効期限を発行年を含めた{}年に設定しました。"
#: pretix/control/forms/event.py:806
#, fuzzy
#| msgid "including all taxes"
msgid "Prices including tax"
msgstr "税込価格"
msgstr "すべての税金を含めて"
#: pretix/control/forms/event.py:807
msgid "Recommended if you sell tickets at least partly to consumers."
msgstr "少なくとも一部を消費者に販売する場合に推奨されます。"
msgstr ""
#: pretix/control/forms/event.py:811
#, fuzzy
#| msgctxt "reporting_timeframe"
#| msgid "All future (excluding today)"
msgid "Prices excluding tax"
msgstr "税込価格"
msgstr "すべての未来(今日を除く)"
#: pretix/control/forms/event.py:812
msgid "Recommended only if you sell tickets primarily to business customers."
msgstr "主に法人顧客にチケットを販売する場合のみ推奨されます。"
msgstr ""
#: pretix/control/forms/event.py:848
#, fuzzy
#| msgid "Date chosen by customer"
msgid "Prices shown to customer"
msgstr "顧客に表示される価格"
msgstr "お客様が選んだ日付"
#: pretix/control/forms/event.py:852
msgid ""
@@ -13644,9 +13657,6 @@ msgid ""
"product, the total tax amount can differ from when it would be computed from "
"the order total."
msgstr ""
"電子インボイスが不要な場合に推奨されます。各製品は表示された税抜価格と税込価"
"格で販売されます。ただし、複数の製品を含む注文では、合計税額が注文合計から計"
"算した場合と異なる可能性があります。"
#: pretix/control/forms/event.py:857
msgid ""
@@ -13655,10 +13665,6 @@ msgid ""
"may be changed to ensure correct rounding, while the net prices will be kept "
"as configured. This may cause the actual payment amount to differ."
msgstr ""
"主に法人顧客に販売し、顧客に税抜価格を表示する場合の電子インボイスに推奨され"
"ます。正確な端数処理を確保するために、一部の製品の税込価格が変更される場合が"
"ありますが、税抜価格は設定どおりに保たれます。これにより実際の支払い金額が異"
"なる場合があります。"
#: pretix/control/forms/event.py:863
msgid ""
@@ -13668,11 +13674,6 @@ msgid ""
"configured whenever possible. Gross prices may still change if they are "
"impossible to derive from a rounded net price."
msgstr ""
"主に消費者に販売する場合の電子インボイスに推奨されます。注文合計の正確な端数"
"処理を確保するために、一部の製品の税込価格または税抜価格が自動的に変更される"
"場合があります。システムは可能な限り設定どおりの税込価格を維持しようとします"
"。ただし、端数処理された税抜価格から算出できない場合は、税込価格が変更される"
"ことがあります。"
#: pretix/control/forms/event.py:961
msgid "Generate invoices for Sales channels"
@@ -14126,7 +14127,7 @@ msgstr "有効な注文"
#: pretix/control/forms/filter.py:220
msgid "Paid (or canceled with paid fee)"
msgstr "支払い済み (または支払い済み手数料でキャンセルされた)"
msgstr "支払われた(または支払われた手数料でキャンセルされた"
#: pretix/control/forms/filter.py:221
#: pretix/control/templates/pretixcontrol/items/question.html:27
@@ -14153,7 +14154,7 @@ msgstr "キャンセル"
#: pretix/control/forms/filter.py:226
msgid "Canceled (fully)"
msgstr "キャンセル済み (全額)"
msgstr "キャンセルされました(完全に)"
#: pretix/control/forms/filter.py:227
msgid "Canceled (fully or with paid fee)"
@@ -14165,11 +14166,11 @@ msgstr "キャンセル済み少なくとも1つのポジション"
#: pretix/control/forms/filter.py:229
msgid "Cancellation requested"
msgstr "キャンセル申請済み"
msgstr "キャンセルがリクエストされました"
#: pretix/control/forms/filter.py:230
msgid "Fully canceled but invoice not canceled"
msgstr "キャンセル済み(請求書はキャンセル)"
msgstr "完全にキャンセルされましたが、請求書はキャンセルされていません"
#: pretix/control/forms/filter.py:232
msgid "Payment process"
@@ -14187,11 +14188,11 @@ msgstr "保留中(期限切れ)"
#: pretix/control/forms/filter.py:236
msgid "Overpaid"
msgstr "過払い済み"
msgstr "過剰な給料"
#: pretix/control/forms/filter.py:237
msgid "Partially paid"
msgstr "一部支払い済み"
msgstr "部分的に支払われました"
#: pretix/control/forms/filter.py:238
msgid "Underpaid (but confirmed)"
@@ -15747,7 +15748,7 @@ msgstr ""
#: pretix/control/forms/orders.py:1037
msgid "I understand that this is not reversible and want to continue"
msgstr "これは元に戻せないことを理解し、続行します"
msgstr ""
#: pretix/control/forms/orders.py:1041
#: pretix/control/templates/pretixcontrol/shredder/download.html:53
@@ -15757,11 +15758,13 @@ msgstr "確認コード"
#: pretix/control/forms/orders.py:1042
msgid ""
"We have just emailed you a confirmation code to enter to confirm this action"
msgstr "この操作を確認するための確認コードをメールで送信しました"
msgstr ""
#: pretix/control/forms/orders.py:1055
#, fuzzy
#| msgid "The confirm code you entered was incorrect."
msgid "The confirmation code is incorrect."
msgstr "確認コードが正しくありません。"
msgstr "入力した確認コードが間違っています。"
#: pretix/control/forms/organizer.py:93
msgid "This slug is already in use. Please choose a different one."
@@ -20690,9 +20693,6 @@ msgid ""
"optionally contain additional rules that depend on the customer's country "
"and type."
msgstr ""
"税ルールは、個々の製品に割り当てることができるさまざまな課税シナリオを定義し"
"ます。各税ルールには既定の税率が含まれ、オプションで顧客の国や種別に応じた追"
"加ルールを含めることができます。"
#: pretix/control/templates/pretixcontrol/event/tax.html:21
msgid "You haven't created any tax rules yet."
@@ -20719,10 +20719,12 @@ msgid "Make default"
msgstr "デフォルトに設定"
#: pretix/control/templates/pretixcontrol/event/tax.html:67
#, python-format
#, fuzzy, python-format
#| msgid "%(count)s event"
#| msgid_plural "%(count)s events"
msgid "%(count)s product"
msgid_plural "%(count)s products"
msgstr[0] "%(count)s個の製品"
msgstr[0] "%(count)s 件のイベント"
#: pretix/control/templates/pretixcontrol/event/tax.html:75
#, python-format
@@ -20735,12 +20737,16 @@ msgid "excl. %(rate)s %%"
msgstr "%(rate)s %%を除く"
#: pretix/control/templates/pretixcontrol/event/tax.html:80
#, fuzzy
#| msgid "Custom rules"
msgid "with custom rules"
msgstr "カスタムルールあり"
msgstr ""
#: pretix/control/templates/pretixcontrol/event/tax.html:110
#, fuzzy
#| msgid "Base settings"
msgid "Tax settings"
msgstr "の設定"
msgstr "ベースの設定"
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:4
#: pretix/control/templates/pretixcontrol/event/tax_delete.html:6
@@ -23481,7 +23487,7 @@ msgstr ""
#: pretix/control/templates/pretixcontrol/order/transactions.html:73
#, python-format
msgid "incl. %(amount)s rounding correction"
msgstr "%(amount)sの端数処理調整を含む"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:5
#: pretix/control/templates/pretixcontrol/orders/bulk_action.html:7
@@ -23584,71 +23590,81 @@ msgstr ""
"空席待ちリストのすべての人が複数のメールを受け取ることになります。"
#: pretix/control/templates/pretixcontrol/orders/cancel.html:84
#, fuzzy
#| msgid "Refund amount"
msgid "Preview refund amount"
msgstr "払い戻し金額のプレビュー"
msgstr "払い戻し金額"
#: pretix/control/templates/pretixcontrol/orders/cancel.html:88
msgid "Cancel all orders"
msgstr "すべての注文をキャンセルします"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:13
#, fuzzy
#| msgid "If you contact us, please send us the following code:"
msgid "If you proceed, the system will do the following:"
msgstr "続行すると、システムは以下を実行します:"
msgstr "お問い合わせの際は、以下のコードをお送りください:"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:19
#, python-format
msgid "%(count)s order will be canceled fully"
msgid_plural "%(count)s orders will be canceled fully"
msgstr[0] "%(count)s件の注文が全額キャンセルされます"
msgstr[0] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:26
#, python-format
msgid "%(count)s order will be canceled partially"
msgid_plural "%(count)s orders will be canceled partially"
msgstr[0] "%(count)s件の注文が一部キャンセルされます"
msgstr[0] ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:36
#, python-format
msgid "%(amount)s are eligible for refunds."
msgstr "%(amount)sが払い戻し対象です。"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:40
msgid ""
"The system will attempt to refund the money automatically if supported by "
"the payment method."
msgstr "当該の決済方法に対応している場合、システムは自動的に払い戻しを試みます。"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:42
msgid "The system will create manual refunds that you need to execute."
msgstr "システムは手動払い戻しを作成しますので、ご自身で実行する必要があります。"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:44
#, fuzzy
#| msgid "Text (if order will not expire automatically)"
msgid "Refunds will not happen automatically."
msgstr "払い戻しは自動的には実行されません。"
msgstr "テキスト(注文が自動的に期限切れにならない場合)"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:52
#, fuzzy
#| msgid "Send information via email"
msgid "Inform all customers via email."
msgstr "メールで情報を送信する"
msgstr "メールで情報を送信する"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:57
msgid "Inform all waiting list contacts via email."
msgstr "すべての空席待ちリストの連絡先にメールで通知する。"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:62
msgid ""
"These numbers are estimates and may change if the data in your event "
"recently changed."
msgstr "これらの数値は推定値であり、イベントのデータが最近変更された場合は変わる可能"
"性があります。"
msgstr ""
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:76
#, python-format
#, fuzzy, python-format
#| msgid "Initiate a refund of %(amount)s"
msgid "Proceed and refund approx. %(amount)s"
msgstr "続行して約%(amount)s払い戻"
msgstr "%(amount)s払い戻しを開始する"
#: pretix/control/templates/pretixcontrol/orders/cancel_confirm.html:80
#, fuzzy
#| msgid "Yes, cancel order"
msgid "Proceed and cancel orders"
msgstr "続行して注文をキャンセルす"
msgstr "はい、注文をキャンセルします"
#: pretix/control/templates/pretixcontrol/orders/export.html:5
#: pretix/control/templates/pretixcontrol/orders/export.html:8
@@ -24043,7 +24059,7 @@ msgstr "請求書はキャンセルされていません"
#: pretix/control/templates/pretixcontrol/orders/index.html:251
msgid "Sum over all pages"
msgstr "全ページの合計"
msgstr "すべてのページに渡り合計する"
#: pretix/control/templates/pretixcontrol/orders/index.html:254
#, python-format
@@ -30197,7 +30213,7 @@ msgstr "手動処理用の完全にカスタマイズ可能な支払い方法。
#: pretix/plugins/paypal2/payment.py:1097
#: pretix/plugins/paypal2/payment.py:1098 pretix/plugins/stripe/payment.py:1816
msgid "PayPal"
msgstr "PayPal"
msgstr "ペイパル"
#: pretix/plugins/paypal/apps.py:53
msgid ""
@@ -30217,7 +30233,7 @@ msgstr ""
#: pretix/plugins/paypal/payment.py:104
msgid "PayPal account"
msgstr "PayPalアカウント"
msgstr "ペイパルアカウント"
#: pretix/plugins/paypal/payment.py:117 pretix/plugins/paypal2/payment.py:114
#, python-brace-format
@@ -30314,7 +30330,7 @@ msgstr "PayPalの支払いID"
#: pretix/plugins/paypal/payment.py:711 pretix/plugins/paypal2/payment.py:1080
msgid "PayPal sale ID"
msgstr "PayPalの売上ID"
msgstr "ペイパルの売上ID"
#: pretix/plugins/paypal/templates/pretixplugins/paypal/checkout_payment_confirm.html:3
#: pretix/plugins/paypal2/templates/pretixplugins/paypal2/checkout_payment_confirm.html:19

View File

@@ -20,12 +20,10 @@
# <https://www.gnu.org/licenses/>.
#
import datetime
from collections import namedtuple
from urllib.parse import urlparse
import vobject
from django.conf import settings
from django.db.models import prefetch_related_objects
from django.utils.formats import date_format
from django.utils.translation import gettext as _
@@ -124,109 +122,61 @@ def get_private_icals(event, positions):
creation_time = datetime.datetime.now(datetime.timezone.utc)
calobjects = []
calentries = set() # using set for automatic deduplication of CalEntries
CalEntry = namedtuple('CalEntry', ['summary', 'description', 'location', 'dtstart', 'dtend', 'uid'])
# collecting the positions' calendar entries, preferring the most exact date and time available (positions > subevent > event)
prefetch_related_objects(positions, 'item__program_times')
for p in positions:
ev = p.subevent or event
program_times = p.item.program_times.all()
if program_times:
# if program times have been configured, they are preferred for the position's calendar entries
evs = set(p.subevent or event for p in positions)
for ev in evs:
if isinstance(ev, Event):
url = build_absolute_uri(event, 'presale:event.index')
for index, pt in enumerate(program_times):
summary = _('{event} - {item}').format(event=ev, item=p.item.name)
if event.settings.mail_attach_ical_description:
ctx = get_email_context(event=event, event_or_subevent=ev)
description = format_map(str(event.settings.mail_attach_ical_description), ctx)
else:
# Default description
descr = []
descr.append(_('Tickets: {url}').format(url=url))
descr.append(str(_('Start: {datetime}')).format(
datetime=date_format(pt.start.astimezone(tz), 'SHORT_DATETIME_FORMAT')
))
descr.append(str(_('End: {datetime}')).format(
datetime=date_format(pt.end.astimezone(tz), 'SHORT_DATETIME_FORMAT')
))
# Actual ical organizer field is not useful since it will cause "your invitation was accepted" emails to the organizer
descr.append(_('Organizer: {organizer}').format(organizer=event.organizer.name))
description = '\n'.join(descr)
location = None
dtstart = pt.start.astimezone(tz)
dtend = pt.end.astimezone(tz)
uid = 'pretix-{}-{}-{}-{}@{}'.format(
event.organizer.slug,
event.slug,
p.item.id,
index,
urlparse(url).netloc
)
calentries.add(CalEntry(summary, description, location, dtstart, dtend, uid))
else:
# without program times, the subevent or event times are used for calendar entries, preferring subevents
if p.subevent:
url = build_absolute_uri(event, 'presale:event.index', {
'subevent': p.subevent.pk
})
else:
url = build_absolute_uri(event, 'presale:event.index')
url = build_absolute_uri(event, 'presale:event.index', {
'subevent': ev.pk
})
if event.settings.mail_attach_ical_description:
ctx = get_email_context(event=event, event_or_subevent=ev)
description = format_map(str(event.settings.mail_attach_ical_description), ctx)
else:
# Default description
descr = []
descr.append(_('Tickets: {url}').format(url=url))
if ev.date_admission:
descr.append(str(_('Admission: {datetime}')).format(
datetime=date_format(ev.date_admission.astimezone(tz), 'SHORT_DATETIME_FORMAT')
))
if event.settings.mail_attach_ical_description:
ctx = get_email_context(event=event, event_or_subevent=ev)
description = format_map(str(event.settings.mail_attach_ical_description), ctx)
else:
# Default description
descr = []
descr.append(_('Tickets: {url}').format(url=url))
if ev.date_admission:
descr.append(str(_('Admission: {datetime}')).format(
datetime=date_format(ev.date_admission.astimezone(tz), 'SHORT_DATETIME_FORMAT')
))
# Actual ical organizer field is not useful since it will cause "your invitation was accepted" emails to the organizer
descr.append(_('Organizer: {organizer}').format(organizer=event.organizer.name))
description = '\n'.join(descr)
summary = str(ev.name)
if ev.location:
location = ", ".join(l.strip() for l in str(ev.location).splitlines() if l.strip())
else:
location = None
if event.settings.show_times:
dtstart = ev.date_from.astimezone(tz)
else:
dtstart = ev.date_from.astimezone(tz).date()
if event.settings.show_date_to and ev.date_to:
if event.settings.show_times:
dtend = ev.date_to.astimezone(tz)
else:
# with full-day events date_to in pretix is included (e.g. last day)
# whereas dtend in vcalendar is non-inclusive => add one day for export
dtend = ev.date_to.astimezone(tz).date() + datetime.timedelta(days=1)
else:
dtend = None
uid = 'pretix-{}-{}-{}@{}'.format(
event.organizer.slug,
event.slug,
ev.pk if p.subevent else '0',
urlparse(url).netloc
)
calentries.add(CalEntry(summary, description, location, dtstart, dtend, uid))
# Actual ical organizer field is not useful since it will cause "your invitation was accepted" emails to the organizer
descr.append(_('Organizer: {organizer}').format(organizer=event.organizer.name))
description = '\n'.join(descr)
for calentry in calentries:
cal = vobject.iCalendar()
cal.add('prodid').value = '-//pretix//{}//'.format(settings.PRETIX_INSTANCE_NAME.replace(" ", "_"))
vevent = cal.add('vevent')
vevent.add('summary').value = calentry.summary
vevent.add('description').value = calentry.description
vevent.add('summary').value = str(ev.name)
vevent.add('description').value = description
vevent.add('dtstamp').value = creation_time
if calentry.location:
vevent.add('location').value = calentry.location
vevent.add('uid').value = calentry.uid
vevent.add('dtstart').value = calentry.dtstart
if calentry.dtend:
vevent.add('dtend').value = calentry.dtend
if ev.location:
vevent.add('location').value = ", ".join(l.strip() for l in str(ev.location).splitlines() if l.strip())
vevent.add('uid').value = 'pretix-{}-{}-{}@{}'.format(
event.organizer.slug,
event.slug,
ev.pk if not isinstance(ev, Event) else '0',
urlparse(url).netloc
)
if event.settings.show_times:
vevent.add('dtstart').value = ev.date_from.astimezone(tz)
else:
vevent.add('dtstart').value = ev.date_from.astimezone(tz).date()
if event.settings.show_date_to and ev.date_to:
if event.settings.show_times:
vevent.add('dtend').value = ev.date_to.astimezone(tz)
else:
# with full-day events date_to in pretix is included (e.g. last day)
# whereas dtend in vcalendar is non-inclusive => add one day for export
vevent.add('dtend').value = ev.date_to.astimezone(tz).date() + datetime.timedelta(days=1)
calobjects.append(cal)
return calobjects

View File

@@ -9,6 +9,34 @@
{% endblock %}
{% block inner %}
<h3 class="sr-only">{% trans "Payment" %}</h3>
{% if customer_gift_cards %}
<p><strong>
<span class="sr-only">{% trans "Information" %}</span>
{% trans "The following gift cards are available in your customer account:" %}
</strong></p>
<form method="post">
{% csrf_token %}
<ul class="list-group">
{% for c in customer_gift_cards %}
<li class="list-group-item row">
<div class="col-xs-9" id="gc-code-{{ forloop.counter }}">
{{ c }}
</div>
<div class="col-xs-2 text-right" id="gc-value-{{ forloop.counter }}">
{{ c.value|money:c.currency }}
</div>
<div class="col-xs-1 text-right">
<button name="use_giftcard" value="{{ c.secret }}" title="{% trans "Use gift card" %}"
aria-describedby="gc-code-{{ forloop.counter }} gc-value-{{ forloop.counter }}"
class="btn btn-primary btn-xs">
{% trans "Apply" %}
</button>
</div>
</li>
{% endfor %}
</ul>
</form>
{% endif %}
{% if current_payments %}
<p>{% trans "You already selected the following payment methods:" %}</p>
<form method="post">

View File

@@ -1,33 +0,0 @@
{% load i18n %}
{% load bootstrap3 %}
{% load money %}
{% load rich_text %}
{{ request.event.settings.payment_giftcard_public_description|rich_text }}
{% if customer_gift_cards %}
<p><strong>
<span class="sr-only">{% trans "Information" %}</span>
{% trans "The following gift cards are available in your customer account:" %}
</strong></p>
{% csrf_token %}
<ul class="list-group">
{% for c in customer_gift_cards %}
<li class="list-group-item row row-no-gutters">
<div class="col-sm-8 col-md-9" id="gc-code-{{ forloop.counter }}">
{{ c }}
</div>
<div class="col-sm-2 text-right" id="gc-value-{{ forloop.counter }}">
{{ c.value|money:c.currency }}
</div>
<div class="col-sm-2 col-md-1 text-right">
<button name="use_giftcard" class="btn btn-primary btn-xs use_giftcard" data-value="{{ c.secret }}"
title="{% trans "Use gift card" %}"
aria-describedby="gc-code-{{ forloop.counter }} gc-value-{{ forloop.counter }}">
{% trans "Apply" %}
</button>
</div>
</li>
{% endfor %}
</ul>
{% endif %}
{% bootstrap_form form layout='checkout' %}

View File

@@ -8,10 +8,10 @@
"name": "pretix",
"version": "0.0.0",
"dependencies": {
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^16.0.1",
"rollup": "^2.79.1",
"rollup-plugin-vue": "^5.0.1",
"vue": "^2.7.16",
@@ -33,27 +33,27 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
"integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
"@babel/generator": "^7.28.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helpers": "^7.28.4",
"@babel/parser": "^7.28.5",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.5",
"@babel/types": "^7.28.5",
"@babel/traverse": "^7.28.4",
"@babel/types": "^7.28.4",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -89,12 +89,12 @@
}
},
"node_modules/@babel/generator": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"dependencies": {
"@babel/parser": "^7.28.5",
"@babel/types": "^7.28.5",
"@babel/parser": "^7.28.3",
"@babel/types": "^7.28.2",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -348,9 +348,10 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -391,11 +392,11 @@
}
},
"node_modules/@babel/parser": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
"dependencies": {
"@babel/types": "^7.28.5"
"@babel/types": "^7.28.4"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -405,12 +406,13 @@
}
},
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz",
"integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz",
"integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/traverse": "^7.28.5"
"@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -601,9 +603,9 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz",
"integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz",
"integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1"
},
@@ -646,16 +648,16 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz",
"integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz",
"integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.27.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-globals": "^7.28.0",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-replace-supers": "^7.27.1",
"@babel/traverse": "^7.28.4"
"@babel/traverse": "^7.28.3"
},
"engines": {
"node": ">=6.9.0"
@@ -681,12 +683,12 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz",
"integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz",
"integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/traverse": "^7.28.5"
"@babel/traverse": "^7.28.0"
},
"engines": {
"node": ">=6.9.0"
@@ -773,9 +775,10 @@
}
},
"node_modules/@babel/plugin-transform-exponentiation-operator": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz",
"integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz",
"integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1"
},
@@ -865,9 +868,10 @@
}
},
"node_modules/@babel/plugin-transform-logical-assignment-operators": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz",
"integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz",
"integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1"
},
@@ -926,14 +930,15 @@
}
},
"node_modules/@babel/plugin-transform-modules-systemjs": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz",
"integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz",
"integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==",
"license": "MIT",
"dependencies": {
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helper-module-transforms": "^7.27.1",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5",
"@babel/traverse": "^7.28.5"
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1020,15 +1025,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz",
"integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz",
"integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==",
"dependencies": {
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.28.0",
"@babel/plugin-transform-parameters": "^7.27.7",
"@babel/traverse": "^7.28.4"
"@babel/traverse": "^7.28.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1069,9 +1074,10 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz",
"integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
"integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
@@ -1146,9 +1152,9 @@
}
},
"node_modules/@babel/plugin-transform-regenerator": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz",
"integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz",
"integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1"
},
@@ -1330,15 +1336,15 @@
}
},
"node_modules/@babel/preset-env": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz",
"integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz",
"integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==",
"dependencies": {
"@babel/compat-data": "^7.28.5",
"@babel/compat-data": "^7.28.0",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-validator-option": "^7.27.1",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1",
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
@@ -1351,42 +1357,42 @@
"@babel/plugin-transform-async-generator-functions": "^7.28.0",
"@babel/plugin-transform-async-to-generator": "^7.27.1",
"@babel/plugin-transform-block-scoped-functions": "^7.27.1",
"@babel/plugin-transform-block-scoping": "^7.28.5",
"@babel/plugin-transform-block-scoping": "^7.28.0",
"@babel/plugin-transform-class-properties": "^7.27.1",
"@babel/plugin-transform-class-static-block": "^7.28.3",
"@babel/plugin-transform-classes": "^7.28.4",
"@babel/plugin-transform-classes": "^7.28.3",
"@babel/plugin-transform-computed-properties": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.28.5",
"@babel/plugin-transform-destructuring": "^7.28.0",
"@babel/plugin-transform-dotall-regex": "^7.27.1",
"@babel/plugin-transform-duplicate-keys": "^7.27.1",
"@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1",
"@babel/plugin-transform-dynamic-import": "^7.27.1",
"@babel/plugin-transform-explicit-resource-management": "^7.28.0",
"@babel/plugin-transform-exponentiation-operator": "^7.28.5",
"@babel/plugin-transform-exponentiation-operator": "^7.27.1",
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
"@babel/plugin-transform-for-of": "^7.27.1",
"@babel/plugin-transform-function-name": "^7.27.1",
"@babel/plugin-transform-json-strings": "^7.27.1",
"@babel/plugin-transform-literals": "^7.27.1",
"@babel/plugin-transform-logical-assignment-operators": "^7.28.5",
"@babel/plugin-transform-logical-assignment-operators": "^7.27.1",
"@babel/plugin-transform-member-expression-literals": "^7.27.1",
"@babel/plugin-transform-modules-amd": "^7.27.1",
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
"@babel/plugin-transform-modules-systemjs": "^7.28.5",
"@babel/plugin-transform-modules-systemjs": "^7.27.1",
"@babel/plugin-transform-modules-umd": "^7.27.1",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1",
"@babel/plugin-transform-new-target": "^7.27.1",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
"@babel/plugin-transform-numeric-separator": "^7.27.1",
"@babel/plugin-transform-object-rest-spread": "^7.28.4",
"@babel/plugin-transform-object-rest-spread": "^7.28.0",
"@babel/plugin-transform-object-super": "^7.27.1",
"@babel/plugin-transform-optional-catch-binding": "^7.27.1",
"@babel/plugin-transform-optional-chaining": "^7.28.5",
"@babel/plugin-transform-optional-chaining": "^7.27.1",
"@babel/plugin-transform-parameters": "^7.27.7",
"@babel/plugin-transform-private-methods": "^7.27.1",
"@babel/plugin-transform-private-property-in-object": "^7.27.1",
"@babel/plugin-transform-property-literals": "^7.27.1",
"@babel/plugin-transform-regenerator": "^7.28.4",
"@babel/plugin-transform-regenerator": "^7.28.3",
"@babel/plugin-transform-regexp-modifiers": "^7.27.1",
"@babel/plugin-transform-reserved-words": "^7.27.1",
"@babel/plugin-transform-shorthand-properties": "^7.27.1",
@@ -1448,16 +1454,16 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
"@babel/generator": "^7.28.3",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.5",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.5",
"@babel/types": "^7.28.4",
"debug": "^4.3.1"
},
"engines": {
@@ -1465,12 +1471,12 @@
}
},
"node_modules/@babel/types": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5"
"@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1517,9 +1523,9 @@
}
},
"node_modules/@rollup/plugin-babel": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.1.0.tgz",
"integrity": "sha512-dFZNuFD2YRcoomP4oYf+DvQNSUA9ih+A3vUqopQx5EdtPGo3WBnQcI/S8pwpz91UsGfL0HsMSOlaMld8HrbubA==",
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz",
"integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==",
"dependencies": {
"@babel/helper-module-imports": "^7.18.6",
"@rollup/pluginutils": "^5.0.1"
@@ -1542,9 +1548,10 @@
}
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz",
"integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz",
"integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==",
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",
@@ -3783,24 +3790,24 @@
}
},
"@babel/compat-data": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
"integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw=="
},
"@babel/core": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"requires": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
"@babel/generator": "^7.28.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helpers": "^7.28.4",
"@babel/parser": "^7.28.5",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.5",
"@babel/types": "^7.28.5",
"@babel/traverse": "^7.28.4",
"@babel/types": "^7.28.4",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -3822,12 +3829,12 @@
}
},
"@babel/generator": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"requires": {
"@babel/parser": "^7.28.5",
"@babel/types": "^7.28.5",
"@babel/parser": "^7.28.3",
"@babel/types": "^7.28.2",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -4004,9 +4011,9 @@
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
},
"@babel/helper-validator-identifier": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="
},
"@babel/helper-validator-option": {
"version": "7.27.1",
@@ -4033,20 +4040,20 @@
}
},
"@babel/parser": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
"requires": {
"@babel/types": "^7.28.5"
"@babel/types": "^7.28.4"
}
},
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz",
"integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz",
"integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/traverse": "^7.28.5"
"@babel/traverse": "^7.27.1"
}
},
"@babel/plugin-bugfix-safari-class-field-initializer-scope": {
@@ -4152,9 +4159,9 @@
}
},
"@babel/plugin-transform-block-scoping": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz",
"integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz",
"integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1"
}
@@ -4178,16 +4185,16 @@
}
},
"@babel/plugin-transform-classes": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz",
"integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz",
"integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.27.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-globals": "^7.28.0",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-replace-supers": "^7.27.1",
"@babel/traverse": "^7.28.4"
"@babel/traverse": "^7.28.3"
}
},
"@babel/plugin-transform-computed-properties": {
@@ -4200,12 +4207,12 @@
}
},
"@babel/plugin-transform-destructuring": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz",
"integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz",
"integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/traverse": "^7.28.5"
"@babel/traverse": "^7.28.0"
}
},
"@babel/plugin-transform-dotall-regex": {
@@ -4252,9 +4259,9 @@
}
},
"@babel/plugin-transform-exponentiation-operator": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz",
"integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz",
"integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1"
}
@@ -4303,9 +4310,9 @@
}
},
"@babel/plugin-transform-logical-assignment-operators": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz",
"integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz",
"integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1"
}
@@ -4337,14 +4344,14 @@
}
},
"@babel/plugin-transform-modules-systemjs": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz",
"integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz",
"integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==",
"requires": {
"@babel/helper-module-transforms": "^7.28.3",
"@babel/helper-module-transforms": "^7.27.1",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5",
"@babel/traverse": "^7.28.5"
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.1"
}
},
"@babel/plugin-transform-modules-umd": {
@@ -4390,15 +4397,15 @@
}
},
"@babel/plugin-transform-object-rest-spread": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz",
"integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz",
"integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==",
"requires": {
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.28.0",
"@babel/plugin-transform-parameters": "^7.27.7",
"@babel/traverse": "^7.28.4"
"@babel/traverse": "^7.28.0"
}
},
"@babel/plugin-transform-object-super": {
@@ -4419,9 +4426,9 @@
}
},
"@babel/plugin-transform-optional-chaining": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz",
"integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
"integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
@@ -4463,9 +4470,9 @@
}
},
"@babel/plugin-transform-regenerator": {
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz",
"integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz",
"integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==",
"requires": {
"@babel/helper-plugin-utils": "^7.27.1"
}
@@ -4564,15 +4571,15 @@
}
},
"@babel/preset-env": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz",
"integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==",
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz",
"integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==",
"requires": {
"@babel/compat-data": "^7.28.5",
"@babel/compat-data": "^7.28.0",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-validator-option": "^7.27.1",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1",
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
@@ -4585,42 +4592,42 @@
"@babel/plugin-transform-async-generator-functions": "^7.28.0",
"@babel/plugin-transform-async-to-generator": "^7.27.1",
"@babel/plugin-transform-block-scoped-functions": "^7.27.1",
"@babel/plugin-transform-block-scoping": "^7.28.5",
"@babel/plugin-transform-block-scoping": "^7.28.0",
"@babel/plugin-transform-class-properties": "^7.27.1",
"@babel/plugin-transform-class-static-block": "^7.28.3",
"@babel/plugin-transform-classes": "^7.28.4",
"@babel/plugin-transform-classes": "^7.28.3",
"@babel/plugin-transform-computed-properties": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.28.5",
"@babel/plugin-transform-destructuring": "^7.28.0",
"@babel/plugin-transform-dotall-regex": "^7.27.1",
"@babel/plugin-transform-duplicate-keys": "^7.27.1",
"@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1",
"@babel/plugin-transform-dynamic-import": "^7.27.1",
"@babel/plugin-transform-explicit-resource-management": "^7.28.0",
"@babel/plugin-transform-exponentiation-operator": "^7.28.5",
"@babel/plugin-transform-exponentiation-operator": "^7.27.1",
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
"@babel/plugin-transform-for-of": "^7.27.1",
"@babel/plugin-transform-function-name": "^7.27.1",
"@babel/plugin-transform-json-strings": "^7.27.1",
"@babel/plugin-transform-literals": "^7.27.1",
"@babel/plugin-transform-logical-assignment-operators": "^7.28.5",
"@babel/plugin-transform-logical-assignment-operators": "^7.27.1",
"@babel/plugin-transform-member-expression-literals": "^7.27.1",
"@babel/plugin-transform-modules-amd": "^7.27.1",
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
"@babel/plugin-transform-modules-systemjs": "^7.28.5",
"@babel/plugin-transform-modules-systemjs": "^7.27.1",
"@babel/plugin-transform-modules-umd": "^7.27.1",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1",
"@babel/plugin-transform-new-target": "^7.27.1",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
"@babel/plugin-transform-numeric-separator": "^7.27.1",
"@babel/plugin-transform-object-rest-spread": "^7.28.4",
"@babel/plugin-transform-object-rest-spread": "^7.28.0",
"@babel/plugin-transform-object-super": "^7.27.1",
"@babel/plugin-transform-optional-catch-binding": "^7.27.1",
"@babel/plugin-transform-optional-chaining": "^7.28.5",
"@babel/plugin-transform-optional-chaining": "^7.27.1",
"@babel/plugin-transform-parameters": "^7.27.7",
"@babel/plugin-transform-private-methods": "^7.27.1",
"@babel/plugin-transform-private-property-in-object": "^7.27.1",
"@babel/plugin-transform-property-literals": "^7.27.1",
"@babel/plugin-transform-regenerator": "^7.28.4",
"@babel/plugin-transform-regenerator": "^7.28.3",
"@babel/plugin-transform-regexp-modifiers": "^7.27.1",
"@babel/plugin-transform-reserved-words": "^7.27.1",
"@babel/plugin-transform-shorthand-properties": "^7.27.1",
@@ -4668,26 +4675,26 @@
}
},
"@babel/traverse": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
"requires": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
"@babel/generator": "^7.28.3",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.5",
"@babel/parser": "^7.28.4",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.5",
"@babel/types": "^7.28.4",
"debug": "^4.3.1"
}
},
"@babel/types": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
"requires": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5"
"@babel/helper-validator-identifier": "^7.27.1"
}
},
"@jridgewell/gen-mapping": {
@@ -4728,18 +4735,18 @@
}
},
"@rollup/plugin-babel": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.1.0.tgz",
"integrity": "sha512-dFZNuFD2YRcoomP4oYf+DvQNSUA9ih+A3vUqopQx5EdtPGo3WBnQcI/S8pwpz91UsGfL0HsMSOlaMld8HrbubA==",
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz",
"integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==",
"requires": {
"@babel/helper-module-imports": "^7.18.6",
"@rollup/pluginutils": "^5.0.1"
}
},
"@rollup/plugin-node-resolve": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz",
"integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz",
"integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==",
"requires": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",

View File

@@ -4,10 +4,10 @@
"private": true,
"scripts": {},
"dependencies": {
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^16.0.1",
"vue": "^2.7.16",
"rollup": "^2.79.1",
"rollup-plugin-vue": "^5.0.1",

View File

@@ -46,8 +46,7 @@ from tests.const import SAMPLE_PNG
from pretix.base.models import (
CartPosition, InvoiceAddress, Item, ItemAddOn, ItemBundle, ItemCategory,
ItemProgramTime, ItemVariation, Order, OrderPosition, Question,
QuestionOption, Quota,
ItemVariation, Order, OrderPosition, Question, QuestionOption, Quota,
)
from pretix.base.models.orders import OrderFee
@@ -332,7 +331,6 @@ TEST_ITEM_RES = {
"variations": [],
"addons": [],
"bundles": [],
"program_times": [],
"show_quota_left": None,
"original_price": None,
"free_price_suggestion": None,
@@ -511,24 +509,6 @@ def test_item_detail_bundles(token_client, organizer, event, team, item, categor
assert res == resp.data
@pytest.mark.django_db
def test_item_detail_program_times(token_client, organizer, event, team, item, category):
with scopes_disabled():
item.program_times.create(item=item, start=datetime(2017, 12, 27, 0, 0, 0, tzinfo=timezone.utc),
end=datetime(2017, 12, 28, 0, 0, 0, tzinfo=timezone.utc))
res = dict(TEST_ITEM_RES)
res["id"] = item.pk
res["program_times"] = [{
"start": "2017-12-27T00:00:00Z",
"end": "2017-12-28T00:00:00Z",
}]
resp = token_client.get('/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug,
item.pk))
assert resp.status_code == 200
assert res == resp.data
@pytest.mark.django_db
def test_item_create(token_client, organizer, event, item, category, taxrule, membership_type):
resp = token_client.post(
@@ -1092,57 +1072,6 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category,
assert resp.content.decode() == '{"bundles":["The chosen variation does not belong to this item."]}'
@pytest.mark.django_db
def test_item_create_with_product_time(token_client, organizer, event, item, category, taxrule):
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
{
"category": category.pk,
"name": {
"en": "Ticket"
},
"active": True,
"description": None,
"default_price": "23.00",
"free_price": False,
"tax_rate": "19.00",
"tax_rule": taxrule.pk,
"admission": True,
"issue_giftcard": False,
"position": 0,
"picture": None,
"available_from": None,
"available_until": None,
"require_voucher": False,
"hide_without_voucher": False,
"allow_cancel": True,
"min_per_order": None,
"max_per_order": None,
"checkin_attention": False,
"checkin_text": None,
"has_variations": False,
"program_times": [
{
"start": "2017-12-27T00:00:00Z",
"end": "2017-12-28T00:00:00Z",
},
{
"start": "2017-12-29T00:00:00Z",
"end": "2017-12-30T00:00:00Z",
}
]
},
format='json'
)
assert resp.status_code == 201
with scopes_disabled():
new_item = Item.objects.get(pk=resp.data['id'])
assert new_item.program_times.first().start == datetime(2017, 12, 27, 0, 0, 0, tzinfo=timezone.utc)
assert new_item.program_times.first().end == datetime(2017, 12, 28, 0, 0, 0, tzinfo=timezone.utc)
assert new_item.program_times.last().start == datetime(2017, 12, 29, 0, 0, 0, tzinfo=timezone.utc)
assert new_item.program_times.last().end == datetime(2017, 12, 30, 0, 0, 0, tzinfo=timezone.utc)
@pytest.mark.django_db(transaction=True)
def test_item_update(token_client, organizer, event, item, category, item2, category2, taxrule2):
resp = token_client.patch(
@@ -1218,8 +1147,8 @@ def test_item_update(token_client, organizer, event, item, category, item2, cate
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, program times or variations via ' \
'PATCH/PUT is not supported. Please use the dedicated nested endpoint."]}'
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use ' \
'the dedicated nested endpoint."]}'
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug, item.pk),
@@ -1236,8 +1165,8 @@ def test_item_update(token_client, organizer, event, item, category, item2, cate
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, program times or variations via ' \
'PATCH/PUT is not supported. Please use the dedicated nested endpoint."]}'
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use ' \
'the dedicated nested endpoint."]}'
item.personalized = True
item.admission = True
@@ -1393,8 +1322,8 @@ def test_item_update_with_variation(token_client, organizer, event, item):
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, program times or variations via ' \
'PATCH/PUT is not supported. Please use the dedicated nested endpoint."]}'
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use ' \
'the dedicated nested endpoint."]}'
@pytest.mark.django_db
@@ -1416,8 +1345,8 @@ def test_item_update_with_addon(token_client, organizer, event, item, category):
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, program times or variations via ' \
'PATCH/PUT is not supported. Please use the dedicated nested endpoint."]}'
assert resp.content.decode() == '{"non_field_errors":["Updating add-ons, bundles, or variations via PATCH/PUT is not supported. Please use ' \
'the dedicated nested endpoint."]}'
@pytest.mark.django_db
@@ -1952,123 +1881,6 @@ def test_addons_delete(token_client, organizer, event, item, addon):
assert not item.addons.filter(pk=addon.id).exists()
@pytest.fixture
def program_time(item, category):
return item.program_times.create(start=datetime(2017, 12, 27, 0, 0, 0, tzinfo=timezone.utc),
end=datetime(2017, 12, 28, 0, 0, 0, tzinfo=timezone.utc))
@pytest.fixture
def program_time2(item, category):
return item.program_times.create(start=datetime(2017, 12, 29, 0, 0, 0, tzinfo=timezone.utc),
end=datetime(2017, 12, 30, 0, 0, 0, tzinfo=timezone.utc))
TEST_PROGRAM_TIMES_RES = {
0: {
"start": "2017-12-27T00:00:00Z",
"end": "2017-12-28T00:00:00Z",
},
1: {
"start": "2017-12-29T00:00:00Z",
"end": "2017-12-30T00:00:00Z",
}
}
@pytest.mark.django_db
def test_program_times_list(token_client, organizer, event, item, program_time, program_time2):
res = dict(TEST_PROGRAM_TIMES_RES)
res[0]["id"] = program_time.pk
res[1]["id"] = program_time2.pk
resp = token_client.get('/api/v1/organizers/{}/events/{}/items/{}/program_times/'.format(organizer.slug, event.slug,
item.pk))
assert resp.status_code == 200
assert res[0]['start'] == resp.data['results'][0]['start']
assert res[0]['end'] == resp.data['results'][0]['end']
assert res[0]['id'] == resp.data['results'][0]['id']
assert res[1]['start'] == resp.data['results'][1]['start']
assert res[1]['end'] == resp.data['results'][1]['end']
assert res[1]['id'] == resp.data['results'][1]['id']
@pytest.mark.django_db
def test_program_times_detail(token_client, organizer, event, item, program_time):
res = dict(TEST_PROGRAM_TIMES_RES)
res[0]["id"] = program_time.pk
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/{}/'.format(organizer.slug, event.slug,
item.pk, program_time.pk))
assert resp.status_code == 200
assert res[0] == resp.data
@pytest.mark.django_db
def test_program_times_create(token_client, organizer, event, item):
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/'.format(organizer.slug, event.slug, item.pk),
{
"start": "2017-12-27T00:00:00Z",
"end": "2017-12-28T00:00:00Z"
},
format='json'
)
assert resp.status_code == 201
with scopes_disabled():
program_time = ItemProgramTime.objects.get(pk=resp.data['id'])
assert datetime(2017, 12, 27, 0, 0, 0, tzinfo=timezone.utc) == program_time.start
assert datetime(2017, 12, 28, 0, 0, 0, tzinfo=timezone.utc) == program_time.end
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/'.format(organizer.slug, event.slug, item.pk),
{
"start": "2017-12-28T00:00:00Z",
"end": "2017-12-27T00:00:00Z"
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["The program end must not be before the program start."]}'
@pytest.mark.django_db
def test_program_times_update(token_client, organizer, event, item, program_time):
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/{}/'.format(organizer.slug, event.slug, item.pk,
program_time.pk),
{
"start": "2017-12-26T00:00:00Z"
},
format='json'
)
assert resp.status_code == 200
with scopes_disabled():
program_time = ItemProgramTime.objects.get(pk=resp.data['id'])
assert datetime(2017, 12, 26, 0, 0, 0, tzinfo=timezone.utc) == program_time.start
assert datetime(2017, 12, 28, 0, 0, 0, tzinfo=timezone.utc) == program_time.end
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/{}/'.format(organizer.slug, event.slug, item.pk,
program_time.pk),
{
"start": "2017-12-30T00:00:00Z"
},
format='json'
)
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["The program end must not be before the program start."]}'
@pytest.mark.django_db
def test_program_times_delete(token_client, organizer, event, item, program_time):
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/items/{}/program_times/{}/'.format(organizer.slug, event.slug,
item.pk, program_time.pk))
assert resp.status_code == 204
with scopes_disabled():
assert not item.program_times.filter(pk=program_time.id).exists()
@pytest.fixture
def quota(event, item):
q = event.quotas.create(name="Budget Quota", size=200)

View File

@@ -1996,7 +1996,7 @@ def test_pdf_data(token_client, organizer, event, order, django_assert_max_num_q
assert not resp.data['positions'][0].get('pdf_data')
# order list
with django_assert_max_num_queries(33):
with django_assert_max_num_queries(32):
resp = token_client.get('/api/v1/organizers/{}/events/{}/orders/?pdf_data=true'.format(
organizer.slug, event.slug
))

View File

@@ -39,9 +39,7 @@ import pytest
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import (
Event, ItemProgramTime, Organizer, Question, SeatingPlan,
)
from pretix.base.models import Event, Organizer, Question, SeatingPlan
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
@@ -80,10 +78,6 @@ def test_full_clone_same_organizer():
# todo: test that item pictures are copied, not linked
ItemMetaValue.objects.create(item=item1, property=item_meta, value="Foo")
assert item1.meta_data
ItemProgramTime.objects.create(item=item1,
start=datetime.datetime(2017, 12, 27, 0, 0, 0, tzinfo=datetime.timezone.utc),
end=datetime.datetime(2017, 12, 28, 0, 0, 0, tzinfo=datetime.timezone.utc))
assert item1.program_times
item2 = event.items.create(category=category, tax_rule=tax_rule, name="T-shirt", default_price=15,
hidden_if_item_available=item1)
item2v = item2.variations.create(value="red", default_price=15, all_sales_channels=False)
@@ -167,8 +161,6 @@ def test_full_clone_same_organizer():
assert copied_item1.category == copied_event.categories.get(name='Tickets')
assert copied_item1.limit_sales_channels.get() == sc
assert copied_item1.meta_data == item1.meta_data
assert copied_item1.program_times.first().start == item1.program_times.first().start
assert copied_item1.program_times.first().end == item1.program_times.first().end
assert copied_item2.variations.get().meta_data == item2v.meta_data
assert copied_item1.hidden_if_available == copied_q2
assert copied_item1.grant_membership_type == membership_type

View File

@@ -681,10 +681,6 @@ class ItemsTest(ItemFormTest):
self.var2.save()
prop = self.event1.item_meta_properties.create(name="Foo")
self.item2.meta_values.create(property=prop, value="Bar")
self.item2.program_times.create(start=datetime.datetime(2017, 12, 27, 0, 0, 0,
tzinfo=datetime.timezone.utc),
end=datetime.datetime(2017, 12, 28, 0, 0, 0,
tzinfo=datetime.timezone.utc))
doc = self.get_doc('/control/event/%s/%s/items/add?copy_from=%d' % (self.orga1.slug, self.event1.slug, self.item2.pk))
data = extract_form_fields(doc.select("form")[0])
@@ -713,8 +709,6 @@ class ItemsTest(ItemFormTest):
assert i_new.meta_data == i_old.meta_data == {"Foo": "Bar"}
assert set(i_new.questions.all()) == set(i_old.questions.all())
assert set([str(v.value) for v in i_new.variations.all()]) == set([str(v.value) for v in i_old.variations.all()])
assert i_old.program_times.first().start == i_new.program_times.first().start
assert i_old.program_times.first().end == i_new.program_times.first().end
def test_add_to_existing_quota(self):
with scopes_disabled():