forked from CGM_Public/pretix_original
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f78e54f2a1 | |||
| 23a52eb12a | |||
| 79ecb231f2 | |||
| 08de7f59a3 | |||
| 0de3c33bab | |||
| a4ae8b0e66 | |||
| be1bf81298 | |||
| b7528ae1cf | |||
| 4f6712ccbe | |||
| 939335f94b | |||
| c849276a35 | |||
| 8e9f0f07a1 | |||
| 389884d191 | |||
| d8c2c82da7 | |||
| c3ed3d4899 | |||
| e9235cd433 | |||
| 975b6d800a | |||
| ee260c8231 | |||
| f7fddc05dd | |||
| eaa61c7795 | |||
| d4994258e6 | |||
| 9b50ec2d74 | |||
| 447b6b7fee | |||
| 40f763c999 | |||
| 6a3d05be9e | |||
| 766447f021 | |||
| 5fbeb90f00 | |||
| c01cc85eda | |||
| 4a054da6ee | |||
| 583a2b6572 | |||
| fbe025afb2 | |||
| 66e6191122 | |||
| 0f26f0787c | |||
| 62a86c9b4a | |||
| 07318be4c9 | |||
| 3c8ef2c620 | |||
| a858f47220 | |||
| 381fa5e1cd | |||
| 1539eea664 | |||
| 3d41d1331a | |||
| 00848b3339 | |||
| d174b11c6a | |||
| a501ce496a | |||
| de277cc959 | |||
| 12b3ae81d6 | |||
| fcdb40dda0 | |||
| f65cf8e86a | |||
| 12540238b7 | |||
| 398a30e33a | |||
| 3410640618 | |||
| 7b45cfccc2 | |||
| 33f503aea1 | |||
| 3fd650081b | |||
| b622854be6 | |||
| 6d00daa9ee | |||
| f27148998a | |||
| 4a0369cc37 | |||
| 76aaf61e19 | |||
| dd1e5fa929 | |||
| 4a2516e303 | |||
| cf06712eca | |||
| 6185d675f0 | |||
| a53cd3abce | |||
| ebe86a17fb | |||
| d189b16ee7 | |||
| d70ce4491a | |||
| 607ff48d70 | |||
| 4bab44ca85 | |||
| a5cdb485d0 | |||
| 282ef792c4 | |||
| 6cd888a1dc | |||
| 2e5b80c83c | |||
| 4511110069 | |||
| 1af1d8c658 | |||
| 9f6a3f9a6a | |||
| 1c03d5d305 | |||
| 69a1fccd20 | |||
| 2a54aa2d83 |
@@ -43,6 +43,7 @@ seating_plan integer If reserved sea
|
||||
seat_category_mapping object An object mapping categories of the seating plan
|
||||
(strings) to items in the event (integers or ``null``).
|
||||
timezone string Event timezone name
|
||||
item_meta_properties object Item-specific meta data parameters and default values.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -79,6 +80,10 @@ timezone string Event timezone
|
||||
|
||||
The attribute ``timezone`` has been added.
|
||||
|
||||
.. versionchanged:: 3.7
|
||||
|
||||
The attribute ``item_meta_properties`` has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -133,6 +138,7 @@ Endpoints
|
||||
"seating_plan": null,
|
||||
"seat_category_mapping": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
@@ -204,6 +210,7 @@ Endpoints
|
||||
"seat_category_mapping": {},
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
@@ -256,6 +263,7 @@ Endpoints
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
@@ -290,6 +298,7 @@ Endpoints
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
@@ -344,6 +353,7 @@ Endpoints
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
@@ -378,6 +388,7 @@ Endpoints
|
||||
"seat_category_mapping": {},
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
@@ -444,6 +455,7 @@ Endpoints
|
||||
"seat_category_mapping": {},
|
||||
"meta_data": {},
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer",
|
||||
"pretix.plugins.stripe",
|
||||
|
||||
@@ -59,6 +59,9 @@ Endpoints
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string secret: Only show gift cards with the given secret.
|
||||
:query boolean testmode: Filter for gift cards that are (not) in test mode.
|
||||
:query boolean include_accepted: Also show gift cards issued by other organizers that are accepted by this organizer.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
@@ -94,6 +97,7 @@ Endpoints
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param id: The ``id`` field of the gift card to fetch
|
||||
:query boolean include_accepted: Also show gift cards issued by other organizers that are accepted by this organizer.
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
@@ -227,6 +231,7 @@ Endpoints
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param id: The ``id`` field of the gift card to modify
|
||||
:query boolean include_accepted: Also show gift cards issued by other organizers that are accepted by this organizer.
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The gift card could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
@@ -114,6 +114,7 @@ bundles list of objects Definition of b
|
||||
└ designated_price money (string) Designated price of the bundled product. This will be
|
||||
used to split the price of the base item e.g. for mixed
|
||||
taxation. This is not added to the price.
|
||||
meta_data object Values set for event-specific meta data parameters.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
@@ -154,6 +155,10 @@ bundles list of objects Definition of b
|
||||
|
||||
The ``show_quota_left``, ``allow_waitinglist``, and ``hidden_if_available`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 3.7
|
||||
|
||||
The attribute ``meta_data`` has been added.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
@@ -208,6 +213,7 @@ Endpoints
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"issue_giftcard": false,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
@@ -303,6 +309,7 @@ Endpoints
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"issue_giftcard": false,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
@@ -379,6 +386,7 @@ Endpoints
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"issue_giftcard": false,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
@@ -442,6 +450,7 @@ Endpoints
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"issue_giftcard": false,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
@@ -537,6 +546,7 @@ Endpoints
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"issue_giftcard": false,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
|
||||
@@ -891,6 +891,13 @@ Creating orders
|
||||
IDs in the ``addon_to`` field of another position. Note that all add_ons for a specific position need to come
|
||||
immediately after the position itself.
|
||||
|
||||
Starting with pretix 3.7, you can add ``"simulate": true`` to the body to do a "dry run" of your order. This will
|
||||
validate your order and return you an order object with the resulting prices, but will not create an actual order.
|
||||
You can use this for testing or to look up prices. In this case, some attributes are ignored, such as whether
|
||||
to send an email or what payment provider will be used. Note that some returned fields will contain empty values
|
||||
(e.g. all ``id`` fields of positions will be zero) and some will contain fake values (e.g. the order code will
|
||||
always be ``PREVIEW``). pretix plugins will not be triggered, so some special behavior might be missing as well.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
@@ -114,6 +114,17 @@ If you want to disable voucher input in the widget, you can pass the ``disable-v
|
||||
|
||||
<pretix-widget event="https://pretix.eu/demo/democon/" disable-vouchers></pretix-widget>
|
||||
|
||||
Filtering products
|
||||
------------------
|
||||
|
||||
You can filter the products shown in the widget by passing in a list of product IDs::
|
||||
|
||||
<pretix-widget event="https://pretix.eu/demo/democon/" items="23,42"></pretix-widget>
|
||||
|
||||
Alternatively, you can select one or more categories to be shown::
|
||||
|
||||
<pretix-widget event="https://pretix.eu/demo/democon/" categories="12,25"></pretix-widget>
|
||||
|
||||
Multi-event selection
|
||||
---------------------
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "3.6.0"
|
||||
__version__ = "3.7.0.dev0"
|
||||
|
||||
@@ -34,6 +34,19 @@ class MetaDataField(Field):
|
||||
}
|
||||
|
||||
|
||||
class MetaPropertyField(Field):
|
||||
|
||||
def to_representation(self, value):
|
||||
return {
|
||||
v.name: v.default for v in value.item_meta_properties.all()
|
||||
}
|
||||
|
||||
def to_internal_value(self, data):
|
||||
return {
|
||||
'item_meta_properties': data
|
||||
}
|
||||
|
||||
|
||||
class SeatCategoryMappingField(Field):
|
||||
|
||||
def to_representation(self, value):
|
||||
@@ -77,6 +90,7 @@ class TimeZoneField(ChoiceField):
|
||||
|
||||
class EventSerializer(I18nAwareModelSerializer):
|
||||
meta_data = MetaDataField(required=False, source='*')
|
||||
item_meta_properties = MetaPropertyField(required=False, source='*')
|
||||
plugins = PluginsField(required=False, source='*')
|
||||
seat_category_mapping = SeatCategoryMappingField(source='*', required=False)
|
||||
timezone = TimeZoneField(required=False, choices=[(a, a) for a in common_timezones])
|
||||
@@ -86,7 +100,7 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
fields = ('name', 'slug', 'live', 'testmode', 'currency', 'date_from',
|
||||
'date_to', 'date_admission', 'is_public', 'presale_start',
|
||||
'presale_end', 'location', 'geo_lat', 'geo_lon', 'has_subevents', 'meta_data', 'seating_plan',
|
||||
'plugins', 'seat_category_mapping', 'timezone')
|
||||
'plugins', 'seat_category_mapping', 'timezone', 'item_meta_properties')
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
@@ -131,6 +145,12 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
raise ValidationError(_('Meta data property \'{name}\' does not exist.').format(name=key))
|
||||
return value
|
||||
|
||||
@cached_property
|
||||
def item_meta_props(self):
|
||||
return {
|
||||
p.name: p for p in self.context['request'].event.item_meta_properties.all()
|
||||
}
|
||||
|
||||
def validate_seating_plan(self, value):
|
||||
if value and value.organizer != self.context['request'].organizer:
|
||||
raise ValidationError('Invalid seating plan.')
|
||||
@@ -172,6 +192,7 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
@transaction.atomic
|
||||
def create(self, validated_data):
|
||||
meta_data = validated_data.pop('meta_data', None)
|
||||
item_meta_properties = validated_data.pop('item_meta_properties', None)
|
||||
validated_data.pop('seat_category_mapping', None)
|
||||
plugins = validated_data.pop('plugins', settings.PRETIX_PLUGINS_DEFAULT.split(','))
|
||||
tz = validated_data.pop('timezone', None)
|
||||
@@ -188,6 +209,15 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
value=value
|
||||
)
|
||||
|
||||
# Item Meta properties
|
||||
if item_meta_properties is not None:
|
||||
for key, value in item_meta_properties.items():
|
||||
event.item_meta_properties.create(
|
||||
name=key,
|
||||
default=value,
|
||||
event=event
|
||||
)
|
||||
|
||||
# Seats
|
||||
if event.seating_plan:
|
||||
generate_seats(event, None, event.seating_plan, {})
|
||||
@@ -202,6 +232,7 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
@transaction.atomic
|
||||
def update(self, instance, validated_data):
|
||||
meta_data = validated_data.pop('meta_data', None)
|
||||
item_meta_properties = validated_data.pop('item_meta_properties', None)
|
||||
plugins = validated_data.pop('plugins', None)
|
||||
seat_category_mapping = validated_data.pop('seat_category_mapping', None)
|
||||
tz = validated_data.pop('timezone', None)
|
||||
@@ -228,6 +259,26 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
if prop.name not in meta_data:
|
||||
current_object.delete()
|
||||
|
||||
# Item Meta properties
|
||||
if item_meta_properties is not None:
|
||||
current = [imp for imp in event.item_meta_properties.all()]
|
||||
for key, value in item_meta_properties.items():
|
||||
prop = self.item_meta_props.get(key)
|
||||
if prop in current:
|
||||
prop.default = value
|
||||
prop.save()
|
||||
else:
|
||||
prop = event.item_meta_properties.create(
|
||||
name=key,
|
||||
default=value,
|
||||
event=event
|
||||
)
|
||||
current.append(prop)
|
||||
|
||||
for prop in current:
|
||||
if prop.name not in list(item_meta_properties.keys()):
|
||||
prop.delete()
|
||||
|
||||
# Seats
|
||||
if seat_category_mapping is not None or ('seating_plan' in validated_data and validated_data['seating_plan'] is None):
|
||||
current_mappings = {
|
||||
@@ -528,6 +579,7 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
'invoice_address_vatid',
|
||||
'invoice_address_company_required',
|
||||
'invoice_address_beneficiary',
|
||||
'invoice_address_custom_field',
|
||||
'invoice_name_required',
|
||||
'invoice_address_not_asked_free',
|
||||
'invoice_show_payments',
|
||||
|
||||
@@ -2,13 +2,15 @@ from decimal import Decimal
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from pretix.api.serializers.event import MetaDataField
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.base.models import (
|
||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation, Question,
|
||||
QuestionOption, Quota,
|
||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaValue, ItemVariation,
|
||||
Question, QuestionOption, Quota,
|
||||
)
|
||||
|
||||
|
||||
@@ -110,6 +112,7 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
bundles = InlineItemBundleSerializer(many=True, required=False)
|
||||
variations = InlineItemVariationSerializer(many=True, required=False)
|
||||
tax_rate = ItemTaxRateField(source='*', read_only=True)
|
||||
meta_data = MetaDataField(required=False, source='*')
|
||||
|
||||
class Meta:
|
||||
model = Item
|
||||
@@ -119,7 +122,7 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
|
||||
'min_per_order', 'max_per_order', 'checkin_attention', 'has_variations', 'variations',
|
||||
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
|
||||
'show_quota_left', 'hidden_if_available', 'allow_waitinglist', 'issue_giftcard')
|
||||
'show_quota_left', 'hidden_if_available', 'allow_waitinglist', 'issue_giftcard', 'meta_data')
|
||||
read_only_fields = ('has_variations', 'picture')
|
||||
|
||||
def validate(self, data):
|
||||
@@ -167,18 +170,65 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
ItemAddOn.clean_max_min_count(addon_data['max_count'], addon_data['min_count'])
|
||||
return value
|
||||
|
||||
@cached_property
|
||||
def item_meta_properties(self):
|
||||
return {
|
||||
p.name: p for p in self.context['request'].event.item_meta_properties.all()
|
||||
}
|
||||
|
||||
def validate_meta_data(self, value):
|
||||
for key in value['meta_data'].keys():
|
||||
if key not in self.item_meta_properties:
|
||||
raise ValidationError(_('Item meta data property \'{name}\' does not exist.').format(name=key))
|
||||
return value
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, validated_data):
|
||||
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 {}
|
||||
meta_data = validated_data.pop('meta_data', None)
|
||||
item = Item.objects.create(**validated_data)
|
||||
|
||||
for variation_data in variations_data:
|
||||
ItemVariation.objects.create(item=item, **variation_data)
|
||||
for addon_data in addons_data:
|
||||
ItemAddOn.objects.create(base_item=item, **addon_data)
|
||||
for bundle_data in bundles_data:
|
||||
ItemBundle.objects.create(base_item=item, **bundle_data)
|
||||
|
||||
# Meta data
|
||||
if meta_data is not None:
|
||||
for key, value in meta_data.items():
|
||||
ItemMetaValue.objects.create(
|
||||
property=self.item_meta_properties.get(key),
|
||||
value=value,
|
||||
item=item
|
||||
)
|
||||
return item
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
meta_data = validated_data.pop('meta_data', None)
|
||||
item = super().update(instance, validated_data)
|
||||
|
||||
# Meta data
|
||||
if meta_data is not None:
|
||||
current = {mv.property: mv for mv in item.meta_values.select_related('property')}
|
||||
for key, value in meta_data.items():
|
||||
prop = self.item_meta_properties.get(key)
|
||||
if prop in current:
|
||||
current[prop].value = value
|
||||
current[prop].save()
|
||||
else:
|
||||
item.meta_values.create(
|
||||
property=self.item_meta_properties.get(key),
|
||||
value=value
|
||||
)
|
||||
|
||||
for prop, current_object in current.items():
|
||||
if prop.name not in meta_data:
|
||||
current_object.delete()
|
||||
|
||||
return item
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from pretix.base.models.orders import (
|
||||
)
|
||||
from pretix.base.pdf import get_variables
|
||||
from pretix.base.services.cart import error_messages
|
||||
from pretix.base.services.locking import NoLockManager
|
||||
from pretix.base.services.pricing import get_price
|
||||
from pretix.base.settings import COUNTRIES_WITH_STATE_IN_ADDRESS
|
||||
from pretix.base.signals import register_ticket_outputs
|
||||
@@ -96,6 +97,11 @@ class AnswerQuestionOptionsIdentifierField(serializers.Field):
|
||||
return [o.identifier for o in instance.options.all()]
|
||||
|
||||
|
||||
class AnswerQuestionOptionsField(serializers.Field):
|
||||
def to_representation(self, instance: QuestionAnswer):
|
||||
return [o.pk for o in instance.options.all()]
|
||||
|
||||
|
||||
class InlineSeatSerializer(I18nAwareModelSerializer):
|
||||
|
||||
class Meta:
|
||||
@@ -106,6 +112,7 @@ class InlineSeatSerializer(I18nAwareModelSerializer):
|
||||
class AnswerSerializer(I18nAwareModelSerializer):
|
||||
question_identifier = AnswerQuestionIdentifierField(source='*', read_only=True)
|
||||
option_identifiers = AnswerQuestionOptionsIdentifierField(source='*', read_only=True)
|
||||
options = AnswerQuestionOptionsField(source='*', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = QuestionAnswer
|
||||
@@ -189,6 +196,11 @@ class PdfDataSerializer(serializers.Field):
|
||||
for k, v in ev._cached_meta_data.items():
|
||||
res['meta:' + k] = v
|
||||
|
||||
if not hasattr(instance.item, '_cached_meta_data'):
|
||||
instance.item._cached_meta_data = instance.item.meta_data
|
||||
for k, v in instance.item._cached_meta_data.items():
|
||||
res['itemmeta:' + k] = v
|
||||
|
||||
return res
|
||||
|
||||
|
||||
@@ -580,6 +592,28 @@ class CompatibleJSONField(serializers.JSONField):
|
||||
return value
|
||||
|
||||
|
||||
class WrappedList:
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
|
||||
def all(self):
|
||||
return self._data
|
||||
|
||||
|
||||
class WrappedModel:
|
||||
def __init__(self, model):
|
||||
self._wrapped = model
|
||||
|
||||
def __getattr__(self, item):
|
||||
return getattr(self._wrapped, item)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
invoice_address = InvoiceAddressSerializer(required=False)
|
||||
positions = OrderPositionCreateSerializer(many=True, required=True)
|
||||
@@ -600,6 +634,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
force = serializers.BooleanField(default=False, required=False)
|
||||
payment_date = serializers.DateTimeField(required=False, allow_null=True)
|
||||
send_mail = serializers.BooleanField(default=False, required=False)
|
||||
simulate = serializers.BooleanField(default=False, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -609,7 +644,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
model = Order
|
||||
fields = ('code', 'status', 'testmode', 'email', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
|
||||
'invoice_address', 'positions', 'checkin_attention', 'payment_info', 'payment_date', 'consume_carts',
|
||||
'force', 'send_mail')
|
||||
'force', 'send_mail', 'simulate')
|
||||
|
||||
def validate_payment_provider(self, pp):
|
||||
if pp is None:
|
||||
@@ -701,6 +736,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
payment_info = validated_data.pop('payment_info', '{}')
|
||||
payment_date = validated_data.pop('payment_date', now())
|
||||
force = validated_data.pop('force', False)
|
||||
simulate = validated_data.pop('simulate', False)
|
||||
self._send_mail = validated_data.pop('send_mail', False)
|
||||
|
||||
if 'invoice_address' in validated_data:
|
||||
@@ -714,7 +750,10 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
else:
|
||||
ia = None
|
||||
|
||||
with self.context['event'].lock() as now_dt:
|
||||
lockfn = self.context['event'].lock
|
||||
if simulate:
|
||||
lockfn = NoLockManager
|
||||
with lockfn() as now_dt:
|
||||
free_seats = set()
|
||||
seats_seen = set()
|
||||
consume_carts = validated_data.pop('consume_carts', [])
|
||||
@@ -864,11 +903,20 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
order.set_expires(subevents=[p.get('subevent') for p in positions_data])
|
||||
order.meta_info = "{}"
|
||||
order.total = Decimal('0.00')
|
||||
order.save()
|
||||
if simulate:
|
||||
order = WrappedModel(order)
|
||||
order.last_modified = now()
|
||||
order.code = 'PREVIEW'
|
||||
else:
|
||||
order.save()
|
||||
|
||||
if ia:
|
||||
ia.order = order
|
||||
ia.save()
|
||||
if not simulate:
|
||||
ia.order = order
|
||||
ia.save()
|
||||
else:
|
||||
order.invoice_address = ia
|
||||
ia.last_modified = now()
|
||||
|
||||
pos_map = {}
|
||||
for pos_data in positions_data:
|
||||
@@ -880,7 +928,10 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
'_legacy': attendee_name
|
||||
}
|
||||
pos = OrderPosition(**pos_data)
|
||||
pos.order = order
|
||||
if simulate:
|
||||
pos.order = order._wrapped
|
||||
else:
|
||||
pos.order = order
|
||||
if addon_to:
|
||||
pos.addon_to = pos_map[addon_to]
|
||||
|
||||
@@ -911,19 +962,33 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
invoice_address=ia,
|
||||
).gross
|
||||
|
||||
if pos.voucher:
|
||||
Voucher.objects.filter(pk=pos.voucher.pk).update(redeemed=F('redeemed') + 1)
|
||||
pos.save()
|
||||
if simulate:
|
||||
pos = WrappedModel(pos)
|
||||
pos.id = 0
|
||||
answers = []
|
||||
for answ_data in answers_data:
|
||||
options = answ_data.pop('options', [])
|
||||
answ = WrappedModel(QuestionAnswer(**answ_data))
|
||||
answ.options = WrappedList(options)
|
||||
answers.append(answ)
|
||||
pos.answers = answers
|
||||
pos.pseudonymization_id = "PREVIEW"
|
||||
else:
|
||||
if pos.voucher:
|
||||
Voucher.objects.filter(pk=pos.voucher.pk).update(redeemed=F('redeemed') + 1)
|
||||
pos.save()
|
||||
for answ_data in answers_data:
|
||||
options = answ_data.pop('options', [])
|
||||
answ = pos.answers.create(**answ_data)
|
||||
answ.options.add(*options)
|
||||
pos_map[pos.positionid] = pos
|
||||
for answ_data in answers_data:
|
||||
options = answ_data.pop('options', [])
|
||||
answ = pos.answers.create(**answ_data)
|
||||
answ.options.add(*options)
|
||||
|
||||
for cp in delete_cps:
|
||||
cp.delete()
|
||||
if not simulate:
|
||||
for cp in delete_cps:
|
||||
cp.delete()
|
||||
|
||||
order.total = sum([p.price for p in order.positions.all()])
|
||||
order.total = sum([p.price for p in pos_map.values()])
|
||||
fees = []
|
||||
for fee_data in fees_data:
|
||||
is_percentage = fee_data.pop('_treat_value_as_percentage', False)
|
||||
if is_percentage:
|
||||
@@ -955,17 +1020,26 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
fee_data['tax_rule'] = tr
|
||||
fee_data['value'] = val
|
||||
f = OrderFee(**fee_data)
|
||||
f.order = order
|
||||
f.order = order._wrapped if simulate else order
|
||||
f._calculate_tax()
|
||||
f.save()
|
||||
fees.append(f)
|
||||
if not simulate:
|
||||
f.save()
|
||||
else:
|
||||
f = OrderFee(**fee_data)
|
||||
f.order = order
|
||||
f.order = order._wrapped if simulate else order
|
||||
f._calculate_tax()
|
||||
f.save()
|
||||
fees.append(f)
|
||||
if not simulate:
|
||||
f.save()
|
||||
|
||||
order.total += sum([f.value for f in order.fees.all()])
|
||||
order.save(update_fields=['total'])
|
||||
order.total += sum([f.value for f in fees])
|
||||
if simulate:
|
||||
order.fees = fees
|
||||
order.positions = pos_map.values()
|
||||
return order # ignore payments
|
||||
else:
|
||||
order.save(update_fields=['total'])
|
||||
|
||||
if order.total == Decimal('0.00') and validated_data.get('status') == Order.STATUS_PAID and not payment_provider:
|
||||
payment_provider = 'free'
|
||||
|
||||
@@ -466,6 +466,9 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
send_mail = serializer._send_mail
|
||||
order = serializer.instance
|
||||
serializer = OrderSerializer(order, context=serializer.context)
|
||||
if not order.pk:
|
||||
# Simulation
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
order.log_action(
|
||||
'pretix.event.order.placed',
|
||||
@@ -1078,11 +1081,14 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
auth=request.auth
|
||||
)
|
||||
if mark_refunded:
|
||||
mark_order_refunded(
|
||||
r.order,
|
||||
user=request.user if request.user.is_authenticated else None,
|
||||
auth=(request.auth if request.auth else None),
|
||||
)
|
||||
try:
|
||||
mark_order_refunded(
|
||||
r.order,
|
||||
user=request.user if request.user.is_authenticated else None,
|
||||
auth=(request.auth if request.auth else None),
|
||||
)
|
||||
except OrderError as e:
|
||||
raise ValidationError(str(e))
|
||||
elif mark_pending:
|
||||
if r.order.status == Order.STATUS_PAID and r.order.pending_sum > 0:
|
||||
r.order.status = Order.STATUS_PENDING
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import django_filters
|
||||
from django.db import transaction
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.functional import cached_property
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from django_scopes import scopes_disabled
|
||||
from rest_framework import filters, serializers, status, viewsets
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied
|
||||
@@ -98,14 +101,29 @@ class SeatingPlanViewSet(viewsets.ModelViewSet):
|
||||
instance.delete()
|
||||
|
||||
|
||||
with scopes_disabled():
|
||||
class GiftCardFilter(FilterSet):
|
||||
secret = django_filters.CharFilter(field_name='secret', lookup_expr='iexact')
|
||||
|
||||
class Meta:
|
||||
model = GiftCard
|
||||
fields = ['secret', 'testmode']
|
||||
|
||||
|
||||
class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = GiftCardSerializer
|
||||
queryset = GiftCard.objects.none()
|
||||
permission = 'can_manage_gift_cards'
|
||||
write_permission = 'can_manage_gift_cards'
|
||||
filter_backends = (DjangoFilterBackend,)
|
||||
filterset_class = GiftCardFilter
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.organizer.issued_gift_cards.all()
|
||||
if self.request.GET.get('include_accepted') == 'true':
|
||||
qs = self.request.organizer.accepted_gift_cards
|
||||
else:
|
||||
qs = self.request.organizer.issued_gift_cards.all()
|
||||
return qs
|
||||
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
@@ -126,6 +144,8 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_update(self, serializer):
|
||||
if 'include_accepted' in self.request.GET:
|
||||
raise PermissionDenied("Accepted gift cards cannot be updated, use transact instead.")
|
||||
GiftCard.objects.select_for_update().get(pk=self.get_object().pk)
|
||||
old_value = serializer.instance.value
|
||||
value = serializer.validated_data.pop('value')
|
||||
@@ -148,16 +168,19 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
value = serializers.DecimalField(max_digits=10, decimal_places=2).to_internal_value(
|
||||
request.data.get('value')
|
||||
)
|
||||
text = serializers.CharField(allow_blank=True, allow_null=True).to_internal_value(
|
||||
request.data.get('text', '')
|
||||
)
|
||||
if gc.value + value < Decimal('0.00'):
|
||||
return Response({
|
||||
'value': ['The gift card does not have sufficient credit for this operation.']
|
||||
}, status=status.HTTP_409_CONFLICT)
|
||||
gc.transactions.create(value=value)
|
||||
gc.transactions.create(value=value, text=text)
|
||||
gc.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'value': value}
|
||||
data={'value': value, 'text': text}
|
||||
)
|
||||
return Response(GiftCardSerializer(gc).data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@@ -267,6 +267,10 @@ def base_placeholders(sender, **kwargs):
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'event', ['event'], lambda event: event.name, lambda event: event.name
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'event', ['event_or_subevent'], lambda event_or_subevent: event_or_subevent.name,
|
||||
lambda event_or_subevent: event_or_subevent.name
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'event_slug', ['event'], lambda event: event.slug, lambda event: event.slug
|
||||
),
|
||||
@@ -279,6 +283,11 @@ def base_placeholders(sender, **kwargs):
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'currency', ['event'], lambda event: event.currency, lambda event: event.currency
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'refund_amount', ['event_or_subevent', 'refund_amount'],
|
||||
lambda event_or_subevent, refund_amount: LazyCurrencyNumber(refund_amount, event_or_subevent.currency),
|
||||
lambda event_or_subevent: LazyCurrencyNumber(Decimal('42.23'), event_or_subevent.currency)
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'total_with_currency', ['event', 'order'], lambda event, order: LazyCurrencyNumber(order.total,
|
||||
event.currency),
|
||||
|
||||
@@ -457,7 +457,7 @@ class BaseInvoiceAddressForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = InvoiceAddress
|
||||
fields = ('is_business', 'company', 'name_parts', 'street', 'zipcode', 'city', 'country', 'state',
|
||||
'vat_id', 'internal_reference', 'beneficiary')
|
||||
'vat_id', 'internal_reference', 'beneficiary', 'custom_field')
|
||||
widgets = {
|
||||
'is_business': BusinessBooleanRadio,
|
||||
'street': forms.Textarea(attrs={
|
||||
@@ -561,6 +561,11 @@ class BaseInvoiceAddressForm(forms.ModelForm):
|
||||
if not event.settings.invoice_address_beneficiary:
|
||||
del self.fields['beneficiary']
|
||||
|
||||
if event.settings.invoice_address_custom_field:
|
||||
self.fields['custom_field'].label = event.settings.invoice_address_custom_field
|
||||
else:
|
||||
del self.fields['custom_field']
|
||||
|
||||
for k, v in self.fields.items():
|
||||
if v.widget.attrs.get('autocomplete') or k == 'name_parts':
|
||||
v.widget.attrs['autocomplete'] = 'section-invoice billing ' + v.widget.attrs.get('autocomplete', '')
|
||||
|
||||
@@ -459,6 +459,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
|
||||
def _get_intro(self):
|
||||
story = []
|
||||
if self.invoice.custom_field:
|
||||
story.append(Paragraph(
|
||||
'{}: {}'.format(self.invoice.event.settings.invoice_address_custom_field, self.invoice.custom_field),
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
if self.invoice.internal_reference:
|
||||
story.append(Paragraph(
|
||||
pgettext('invoice', 'Customer reference: {reference}').format(reference=self.invoice.internal_reference),
|
||||
|
||||
@@ -13,11 +13,17 @@ class Command(BaseCommand):
|
||||
return parser
|
||||
|
||||
def handle(self, *args, **options):
|
||||
try:
|
||||
from django_extensions.management.commands import shell_plus # noqa
|
||||
cmd = 'shell_plus'
|
||||
except ImportError:
|
||||
cmd = 'shell'
|
||||
|
||||
parser = self.create_parser(sys.argv[0], sys.argv[1])
|
||||
flags = parser.parse_known_args(sys.argv[2:])[1]
|
||||
if "--override" in flags:
|
||||
with scopes_disabled():
|
||||
return call_command("shell_plus", *args, **options)
|
||||
return call_command(cmd, *args, **options)
|
||||
|
||||
lookups = {}
|
||||
for flag in flags:
|
||||
@@ -36,4 +42,4 @@ class Command(BaseCommand):
|
||||
for app_name, app_value in lookups.items()
|
||||
}
|
||||
with scope(**scope_options):
|
||||
return call_command("shell_plus", *args, **options)
|
||||
return call_command(cmd, *args, **options)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 2.2.9 on 2020-02-18 08:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0143_auto_20200217_1211'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='invoiceaddress',
|
||||
name='custom_field',
|
||||
field=models.CharField(max_length=255, null=True, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='invoice',
|
||||
name='custom_field',
|
||||
field=models.CharField(max_length=255, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,42 @@
|
||||
# Generated by Django 2.2.8 on 2020-02-10 10:38
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.base
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0144_invoiceaddress_custom_field'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ItemMetaProperty',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(db_index=True, max_length=50)),
|
||||
('default', models.TextField()),
|
||||
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_meta_properties', to='pretixbase.Event')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=(models.Model, pretix.base.models.base.LoggingMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ItemMetaValue',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('value', models.TextField()),
|
||||
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='meta_values', to='pretixbase.Item')),
|
||||
('property', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_values', to='pretixbase.ItemMetaProperty')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('item', 'property')},
|
||||
},
|
||||
bases=(models.Model, pretix.base.models.base.LoggingMixin),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2.4 on 2020-03-02 11:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0145_auto_20200210_1038'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='giftcardtransaction',
|
||||
name='text',
|
||||
field=models.TextField(null=True),
|
||||
),
|
||||
]
|
||||
@@ -10,9 +10,9 @@ from .event import (
|
||||
from .giftcards import GiftCard, GiftCardAcceptance, GiftCardTransaction
|
||||
from .invoices import Invoice, InvoiceLine, invoice_filename
|
||||
from .items import (
|
||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation, Question,
|
||||
QuestionOption, Quota, SubEventItem, SubEventItemVariation,
|
||||
itempicture_upload_to,
|
||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemMetaProperty, ItemMetaValue,
|
||||
ItemVariation, Question, QuestionOption, Quota, SubEventItem,
|
||||
SubEventItemVariation, itempicture_upload_to,
|
||||
)
|
||||
from .log import LogEntry
|
||||
from .notifications import NotificationSetting
|
||||
|
||||
@@ -94,6 +94,7 @@ class Device(LoggedModel):
|
||||
return {
|
||||
'can_view_orders',
|
||||
'can_change_orders',
|
||||
'can_manage_gift_cards'
|
||||
}
|
||||
|
||||
def get_event_permission_set(self, organizer, event) -> set:
|
||||
|
||||
@@ -515,7 +515,7 @@ class Event(EventMixin, LoggedModel):
|
||||
), tz)
|
||||
|
||||
def copy_data_from(self, other):
|
||||
from . import ItemAddOn, ItemCategory, Item, Question, Quota
|
||||
from . import ItemAddOn, ItemCategory, Item, Question, Quota, ItemMetaValue
|
||||
from ..signals import event_copy_data
|
||||
|
||||
self.plugins = other.plugins
|
||||
@@ -540,6 +540,14 @@ class Event(EventMixin, LoggedModel):
|
||||
c.save()
|
||||
c.log_action('pretix.object.cloned')
|
||||
|
||||
item_meta_properties_map = {}
|
||||
for imp in other.item_meta_properties.all():
|
||||
item_meta_properties_map[imp.pk] = imp
|
||||
imp.pk = None
|
||||
imp.event = self
|
||||
imp.save()
|
||||
imp.log_action('pretix.object.cloned')
|
||||
|
||||
item_map = {}
|
||||
variation_map = {}
|
||||
for i in Item.objects.filter(event=other).prefetch_related('variations'):
|
||||
@@ -561,6 +569,12 @@ class Event(EventMixin, LoggedModel):
|
||||
v.item = i
|
||||
v.save()
|
||||
|
||||
for imv in ItemMetaValue.objects.filter(item__event=other).prefetch_related('item', 'property'):
|
||||
imv.pk = None
|
||||
imv.property = item_meta_properties_map[imv.property.pk]
|
||||
imv.item = item_map[imv.item.pk]
|
||||
imv.save()
|
||||
|
||||
for ia in ItemAddOn.objects.filter(base_item__event=other).prefetch_related('base_item', 'addon_category'):
|
||||
ia.pk = None
|
||||
ia.base_item = item_map[ia.base_item.pk]
|
||||
|
||||
@@ -119,6 +119,7 @@ class GiftCardTransaction(models.Model):
|
||||
blank=True,
|
||||
on_delete=models.PROTECT
|
||||
)
|
||||
text = models.TextField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ("datetime",)
|
||||
|
||||
@@ -111,6 +111,7 @@ class Invoice(models.Model):
|
||||
|
||||
file = models.FileField(null=True, blank=True, upload_to=invoice_filename, max_length=255)
|
||||
internal_reference = models.TextField(blank=True)
|
||||
custom_field = models.CharField(max_length=255, null=True)
|
||||
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
|
||||
@@ -120,13 +121,19 @@ class Invoice(models.Model):
|
||||
|
||||
@property
|
||||
def full_invoice_from(self):
|
||||
taxidrow = ""
|
||||
if self.invoice_from_tax_id:
|
||||
if str(self.invoice_from_country) == "AU":
|
||||
taxidrow = "ABN: %s" % self.invoice_from_tax_id
|
||||
else:
|
||||
taxidrow = pgettext("invoice", "Tax ID: %s") % self.invoice_from_tax_id
|
||||
parts = [
|
||||
self.invoice_from_name,
|
||||
self.invoice_from,
|
||||
(self.invoice_from_zipcode or "") + " " + (self.invoice_from_city or ""),
|
||||
self.invoice_from_country.name if self.invoice_from_country else "",
|
||||
pgettext("invoice", "VAT-ID: %s") % self.invoice_from_vat_id if self.invoice_from_vat_id else "",
|
||||
pgettext("invoice", "Tax ID: %s") % self.invoice_from_tax_id if self.invoice_from_tax_id else "",
|
||||
taxidrow,
|
||||
]
|
||||
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import sys
|
||||
import uuid
|
||||
from collections import Counter
|
||||
from collections import Counter, OrderedDict
|
||||
from datetime import date, datetime, time
|
||||
from decimal import Decimal, DecimalException
|
||||
from typing import Tuple
|
||||
@@ -9,6 +9,7 @@ import dateutil.parser
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.db.models import F, Func, Q, Sum
|
||||
from django.utils import formats
|
||||
@@ -591,6 +592,16 @@ class Item(LoggedModel):
|
||||
if from_date > until_date:
|
||||
raise ValidationError(_('The item\'s availability cannot end before it starts.'))
|
||||
|
||||
@property
|
||||
def meta_data(self):
|
||||
data = {p.name: p.default for p in self.event.item_meta_properties.all()}
|
||||
if hasattr(self, 'meta_values_cached'):
|
||||
data.update({v.property.name: v.value for v in self.meta_values_cached})
|
||||
else:
|
||||
data.update({v.property.name: v.value for v in self.meta_values.select_related('property').all()})
|
||||
|
||||
return OrderedDict((k, v) for k, v in sorted(data.items(), key=lambda k: k[0]))
|
||||
|
||||
|
||||
class ItemVariation(models.Model):
|
||||
"""
|
||||
@@ -1541,3 +1552,57 @@ class Quota(LoggedModel):
|
||||
else:
|
||||
if subevent:
|
||||
raise ValidationError(_('The subevent does not belong to this event.'))
|
||||
|
||||
|
||||
class ItemMetaProperty(LoggedModel):
|
||||
"""
|
||||
An event can have ItemMetaProperty objects attached to define meta information fields
|
||||
for its items. This information can be re-used for example in ticket layouts.
|
||||
|
||||
:param event: The event this property is defined for.
|
||||
:type event: Event
|
||||
:param name: Name
|
||||
:type name: Name of the property, used in various places
|
||||
:param default: Default value
|
||||
:type default: str
|
||||
"""
|
||||
event = models.ForeignKey(Event, related_name="item_meta_properties", on_delete=models.CASCADE)
|
||||
name = models.CharField(
|
||||
max_length=50, db_index=True,
|
||||
help_text=_(
|
||||
"Can not contain spaces or special characters except underscores"
|
||||
),
|
||||
validators=[
|
||||
RegexValidator(
|
||||
regex="^[a-zA-Z0-9_]+$",
|
||||
message=_("The property name may only contain letters, numbers and underscores."),
|
||||
),
|
||||
],
|
||||
verbose_name=_("Name"),
|
||||
)
|
||||
default = models.TextField(blank=True)
|
||||
|
||||
|
||||
class ItemMetaValue(LoggedModel):
|
||||
"""
|
||||
A meta-data value assigned to an item.
|
||||
|
||||
:param item: The item this metadata is valid for
|
||||
:type item: Item
|
||||
:param property: The property this value belongs to
|
||||
:type property: ItemMetaProperty
|
||||
:param value: The actual value
|
||||
:type value: str
|
||||
"""
|
||||
item = models.ForeignKey('Item', on_delete=models.CASCADE, related_name='meta_values')
|
||||
property = models.ForeignKey('ItemMetaProperty', on_delete=models.CASCADE, related_name='item_values')
|
||||
value = models.TextField()
|
||||
|
||||
class Meta:
|
||||
unique_together = ('item', 'property')
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
super().delete(*args, **kwargs)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@@ -426,7 +426,7 @@ class Order(LockModel, LoggedModel):
|
||||
|
||||
def cancel_allowed(self):
|
||||
return (
|
||||
self.status in (Order.STATUS_PENDING, Order.STATUS_PAID) and self.count_positions
|
||||
self.status in (Order.STATUS_PENDING, Order.STATUS_PAID, Order.STATUS_EXPIRED) and self.count_positions
|
||||
)
|
||||
|
||||
@cached_property
|
||||
@@ -448,16 +448,17 @@ class Order(LockModel, LoggedModel):
|
||||
@cached_property
|
||||
def user_cancel_fee(self):
|
||||
fee = Decimal('0.00')
|
||||
if self.event.settings.cancel_allow_user_paid_keep:
|
||||
fee += self.event.settings.cancel_allow_user_paid_keep
|
||||
if self.event.settings.cancel_allow_user_paid_keep_percentage:
|
||||
fee += self.event.settings.cancel_allow_user_paid_keep_percentage / Decimal('100.0') * self.total
|
||||
if self.event.settings.cancel_allow_user_paid_keep_fees:
|
||||
fee += self.fees.filter(
|
||||
fee_type__in=(OrderFee.FEE_TYPE_PAYMENT, OrderFee.FEE_TYPE_SHIPPING, OrderFee.FEE_TYPE_SERVICE)
|
||||
fee_type__in=(OrderFee.FEE_TYPE_PAYMENT, OrderFee.FEE_TYPE_SHIPPING, OrderFee.FEE_TYPE_SERVICE,
|
||||
OrderFee.FEE_TYPE_CANCELLATION)
|
||||
).aggregate(
|
||||
s=Sum('value')
|
||||
)['s'] or 0
|
||||
if self.event.settings.cancel_allow_user_paid_keep_percentage:
|
||||
fee += self.event.settings.cancel_allow_user_paid_keep_percentage / Decimal('100.0') * (self.total - fee)
|
||||
if self.event.settings.cancel_allow_user_paid_keep:
|
||||
fee += self.event.settings.cancel_allow_user_paid_keep
|
||||
return round_decimal(fee, self.event.currency)
|
||||
|
||||
@property
|
||||
@@ -2094,6 +2095,7 @@ class InvoiceAddress(models.Model):
|
||||
vat_id = models.CharField(max_length=255, blank=True, verbose_name=_('VAT ID'),
|
||||
help_text=_('Only for business customers within the EU.'))
|
||||
vat_id_validated = models.BooleanField(default=False)
|
||||
custom_field = models.CharField(max_length=255, null=True, blank=True)
|
||||
internal_reference = models.TextField(
|
||||
verbose_name=_('Internal reference'),
|
||||
help_text=_('This reference will be printed on your invoice for your convenience.'),
|
||||
|
||||
@@ -431,6 +431,8 @@ class Renderer:
|
||||
return '(error)'
|
||||
if o['content'] == 'other':
|
||||
return o['text']
|
||||
elif o['content'].startswith('itemmeta:'):
|
||||
return op.item.meta_data.get(o['content'][9:]) or ''
|
||||
elif o['content'].startswith('meta:'):
|
||||
return ev.meta_data.get(o['content'][5:]) or ''
|
||||
elif o['content'] in self.variables:
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import (
|
||||
Count, Exists, IntegerField, OuterRef, Subquery, Sum,
|
||||
)
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.email import get_email_context
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
Event, InvoiceAddress, Order, OrderFee, OrderPosition, SubEvent, User,
|
||||
WaitingListEntry,
|
||||
)
|
||||
from pretix.base.services.locking import LockTimeoutException
|
||||
from pretix.base.services.mail import SendMailException, TolerantDict, mail
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, _cancel_order, _try_auto_refund,
|
||||
)
|
||||
from pretix.base.services.tasks import ProfiledEventTask
|
||||
from pretix.celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _send_wle_mail(wle: WaitingListEntry, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent):
|
||||
with language(wle.locale):
|
||||
email_context = get_email_context(event_or_subevent=subevent or wle.event, event=wle.event)
|
||||
try:
|
||||
mail(
|
||||
wle.email,
|
||||
str(subject).format_map(TolerantDict(email_context)),
|
||||
message,
|
||||
email_context,
|
||||
wle.event,
|
||||
locale=wle.locale
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Waiting list canceled email could not be sent')
|
||||
|
||||
|
||||
def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent,
|
||||
refund_amount: Decimal, user: User, positions: list):
|
||||
with language(order.locale):
|
||||
try:
|
||||
ia = order.invoice_address
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
ia = InvoiceAddress()
|
||||
|
||||
email_context = get_email_context(event_or_subevent=subevent or order.event, refund_amount=refund_amount,
|
||||
order=order, position_or_address=ia, event=order.event)
|
||||
real_subject = str(subject).format_map(TolerantDict(email_context))
|
||||
try:
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
user,
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent')
|
||||
|
||||
for p in positions:
|
||||
if subevent and p.subevent_id != subevent.id:
|
||||
continue
|
||||
|
||||
if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
|
||||
real_subject = str(subject).format_map(TolerantDict(email_context))
|
||||
email_context = get_email_context(event_or_subevent=subevent or order.event,
|
||||
event=order.event,
|
||||
refund_amount=refund_amount,
|
||||
position_or_address=p,
|
||||
order=order, position=p)
|
||||
try:
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
position=p,
|
||||
user=user
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent to attendee')
|
||||
|
||||
|
||||
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
|
||||
def cancel_event(self, event: Event, subevent: int, auto_refund: bool, keep_fee_fixed: str,
|
||||
keep_fee_percentage: str, keep_fees: bool,
|
||||
send: bool, send_subject: dict, send_message: dict,
|
||||
send_waitinglist: bool=False, send_waitinglist_subject: dict={}, send_waitinglist_message: dict={},
|
||||
user: int=None):
|
||||
send_subject = LazyI18nString(send_subject)
|
||||
send_message = LazyI18nString(send_message)
|
||||
send_waitinglist_subject = LazyI18nString(send_waitinglist_subject)
|
||||
send_waitinglist_message = LazyI18nString(send_waitinglist_message)
|
||||
if user:
|
||||
user = User.objects.get(pk=user)
|
||||
|
||||
s = OrderPosition.objects.filter(
|
||||
order=OuterRef('pk')
|
||||
).order_by().values('order').annotate(k=Count('id')).values('k')
|
||||
orders_to_cancel = event.orders.annotate(pcnt=Subquery(s, output_field=IntegerField())).filter(
|
||||
status__in=[Order.STATUS_PAID, Order.STATUS_PENDING, Order.STATUS_EXPIRED],
|
||||
pcnt__gt=0
|
||||
).all()
|
||||
|
||||
if subevent:
|
||||
subevent = event.subevents.get(pk=subevent)
|
||||
|
||||
has_subevent = OrderPosition.objects.filter(order_id=OuterRef('pk')).filter(
|
||||
subevent=subevent
|
||||
)
|
||||
has_other_subevent = OrderPosition.objects.filter(order_id=OuterRef('pk')).exclude(
|
||||
subevent=subevent
|
||||
)
|
||||
orders_to_change = orders_to_cancel.annotate(
|
||||
has_subevent=Exists(has_subevent),
|
||||
has_other_subevent=Exists(has_other_subevent),
|
||||
).filter(
|
||||
has_subevent=True, has_other_subevent=True
|
||||
)
|
||||
orders_to_cancel = orders_to_cancel.annotate(
|
||||
has_subevent=Exists(has_subevent),
|
||||
has_other_subevent=Exists(has_other_subevent),
|
||||
).filter(
|
||||
has_subevent=True, has_other_subevent=False
|
||||
)
|
||||
|
||||
subevent.log_action(
|
||||
'pretix.subevent.canceled', user=user,
|
||||
)
|
||||
subevent.active = False
|
||||
subevent.save(update_fields=['active'])
|
||||
subevent.log_action(
|
||||
'pretix.subevent.changed', user=user, data={'active': False, '_source': 'cancel_event'}
|
||||
)
|
||||
else:
|
||||
orders_to_change = event.orders.none()
|
||||
event.log_action(
|
||||
'pretix.event.canceled', user=user,
|
||||
)
|
||||
|
||||
for i in event.items.filter(active=True):
|
||||
i.active = False
|
||||
i.save(update_fields=['active'])
|
||||
i.log_action(
|
||||
'pretix.event.item.changed', user=user, data={'active': False, '_source': 'cancel_event'}
|
||||
)
|
||||
failed = 0
|
||||
|
||||
for o in orders_to_cancel.only('id', 'total'):
|
||||
try:
|
||||
fee = Decimal('0.00')
|
||||
if keep_fees:
|
||||
fee += o.fees.filter(
|
||||
fee_type__in=(OrderFee.FEE_TYPE_PAYMENT, OrderFee.FEE_TYPE_SHIPPING, OrderFee.FEE_TYPE_SERVICE,
|
||||
OrderFee.FEE_TYPE_CANCELLATION)
|
||||
).aggregate(
|
||||
s=Sum('value')
|
||||
)['s'] or 0
|
||||
if keep_fee_percentage:
|
||||
fee += Decimal(keep_fee_percentage) / Decimal('100.00') * (o.total - fee)
|
||||
if keep_fee_fixed:
|
||||
fee += Decimal(keep_fee_fixed)
|
||||
fee = round_decimal(min(fee, o.payment_refund_sum), event.currency)
|
||||
|
||||
_cancel_order(o.pk, user, send_mail=False, cancellation_fee=fee)
|
||||
refund_amount = o.payment_refund_sum
|
||||
|
||||
if auto_refund:
|
||||
_try_auto_refund(o.pk)
|
||||
|
||||
if send:
|
||||
_send_mail(o, send_subject, send_message, subevent, refund_amount, user, o.positions.all())
|
||||
except LockTimeoutException:
|
||||
logger.exception("Could not cancel order")
|
||||
failed += 1
|
||||
except OrderError:
|
||||
logger.exception("Could not cancel order")
|
||||
failed += 1
|
||||
|
||||
for o in orders_to_change.values_list('id', flat=True):
|
||||
with transaction.atomic():
|
||||
o = event.orders.select_for_update().get(pk=o)
|
||||
total = Decimal('0.00')
|
||||
positions = []
|
||||
|
||||
ocm = OrderChangeManager(o, user=user, notify=False)
|
||||
for p in o.positions.all():
|
||||
if p.subevent == subevent:
|
||||
total += p.price
|
||||
ocm.cancel(p)
|
||||
positions.append(p)
|
||||
|
||||
fee = Decimal('0.00')
|
||||
if keep_fee_fixed:
|
||||
fee += Decimal(keep_fee_fixed)
|
||||
if keep_fee_percentage:
|
||||
fee += Decimal(keep_fee_percentage) / Decimal('100.00') * total
|
||||
fee = round_decimal(min(fee, o.payment_refund_sum), event.currency)
|
||||
if fee:
|
||||
f = OrderFee(
|
||||
fee_type=OrderFee.FEE_TYPE_CANCELLATION,
|
||||
value=fee,
|
||||
order=o,
|
||||
tax_rule=o.event.settings.tax_rate_default,
|
||||
)
|
||||
f._calculate_tax()
|
||||
ocm.add_fee(f)
|
||||
|
||||
ocm.commit()
|
||||
refund_amount = o.payment_refund_sum - o.total
|
||||
|
||||
if auto_refund:
|
||||
_try_auto_refund(o.pk)
|
||||
|
||||
if send:
|
||||
_send_mail(o, send_subject, send_message, subevent, refund_amount, user, positions)
|
||||
|
||||
for wle in event.waitinglistentries.filter(subevent=subevent, voucher__isnull=True):
|
||||
_send_wle_mail(wle, send_waitinglist_subject, send_waitinglist_message, subevent)
|
||||
|
||||
return failed
|
||||
@@ -303,32 +303,6 @@ class CartManager:
|
||||
if op.item.require_bundling and not op.addon_to == 'FAKE':
|
||||
raise CartError(error_messages['bundled_only'])
|
||||
|
||||
if op.item.max_per_order or op.item.min_per_order:
|
||||
new_total = (
|
||||
len([1 for p in self.positions if p.item_id == op.item.pk]) +
|
||||
sum([_op.count for _op in self._operations + current_ops
|
||||
if isinstance(_op, self.AddOperation) and _op.item == op.item]) +
|
||||
op.count -
|
||||
len([1 for _op in self._operations + current_ops
|
||||
if isinstance(_op, self.RemoveOperation) and _op.position.item_id == op.item.pk])
|
||||
)
|
||||
|
||||
if op.item.max_per_order and new_total > op.item.max_per_order:
|
||||
raise CartError(
|
||||
_(error_messages['max_items_per_product']) % {
|
||||
'max': op.item.max_per_order,
|
||||
'product': op.item.name
|
||||
}
|
||||
)
|
||||
|
||||
if op.item.min_per_order and new_total < op.item.min_per_order:
|
||||
raise CartError(
|
||||
_(error_messages['min_items_per_product']) % {
|
||||
'min': op.item.min_per_order,
|
||||
'product': op.item.name
|
||||
}
|
||||
)
|
||||
|
||||
def _get_price(self, item: Item, variation: Optional[ItemVariation],
|
||||
voucher: Optional[Voucher], custom_price: Optional[Decimal],
|
||||
subevent: Optional[SubEvent], cp_is_net: bool=None, force_custom_price=False,
|
||||
@@ -787,37 +761,48 @@ class CartManager:
|
||||
|
||||
return vouchers_ok
|
||||
|
||||
def _check_min_per_product(self):
|
||||
per_product = Counter()
|
||||
min_per_product = {}
|
||||
def _check_min_max_per_product(self):
|
||||
items = Counter()
|
||||
for p in self.positions:
|
||||
per_product[p.item_id] += 1
|
||||
min_per_product[p.item.pk] = p.item.min_per_order
|
||||
|
||||
items[p.item] += 1
|
||||
for op in self._operations:
|
||||
if isinstance(op, self.AddOperation):
|
||||
per_product[op.item.pk] += op.count
|
||||
min_per_product[op.item.pk] = op.item.min_per_order
|
||||
items[op.item] += op.count
|
||||
elif isinstance(op, self.RemoveOperation):
|
||||
per_product[op.position.item_id] -= 1
|
||||
min_per_product[op.position.item.pk] = op.position.item.min_per_order
|
||||
items[op.position.item] -= 1
|
||||
|
||||
err = None
|
||||
for itemid, num in per_product.items():
|
||||
min_p = min_per_product[itemid]
|
||||
if min_p and num < min_p:
|
||||
for item, count in items.items():
|
||||
if count == 0:
|
||||
continue
|
||||
|
||||
if item.max_per_order and count > item.max_per_order:
|
||||
raise CartError(
|
||||
_(error_messages['max_items_per_product']) % {
|
||||
'max': item.max_per_order,
|
||||
'product': item.name
|
||||
}
|
||||
)
|
||||
|
||||
if item.min_per_order and count < item.min_per_order:
|
||||
self._operations = [o for o in self._operations if not (
|
||||
isinstance(o, self.AddOperation) and o.item.pk == itemid
|
||||
isinstance(o, self.AddOperation) and o.item.pk == item.pk
|
||||
)]
|
||||
removals = [o.position.pk for o in self._operations if isinstance(o, self.RemoveOperation)]
|
||||
for p in self.positions:
|
||||
if p.item_id == itemid and p.pk not in removals:
|
||||
if p.item_id == item.pk and p.pk not in removals:
|
||||
self._operations.append(self.RemoveOperation(position=p))
|
||||
err = _(error_messages['min_items_per_product_removed']) % {
|
||||
'min': min_p,
|
||||
'product': p.item.name
|
||||
'min': item.min_per_order,
|
||||
'product': item.name
|
||||
}
|
||||
|
||||
if not err:
|
||||
raise CartError(
|
||||
_(error_messages['min_items_per_product']) % {
|
||||
'min': item.min_per_order,
|
||||
'product': item.name
|
||||
}
|
||||
)
|
||||
return err
|
||||
|
||||
def _perform_operations(self):
|
||||
@@ -826,7 +811,7 @@ class CartManager:
|
||||
err = None
|
||||
new_cart_positions = []
|
||||
|
||||
err = err or self._check_min_per_product()
|
||||
err = err or self._check_min_max_per_product()
|
||||
|
||||
self._operations.sort(key=lambda a: self.order[type(a)])
|
||||
seats_seen = set()
|
||||
@@ -1020,8 +1005,9 @@ class CartManager:
|
||||
with lockfn() as now_dt:
|
||||
with transaction.atomic():
|
||||
self.now_dt = now_dt
|
||||
self._extend_expiry_of_valid_existing_positions()
|
||||
err = self._perform_operations() or err
|
||||
if not err:
|
||||
self._extend_expiry_of_valid_existing_positions()
|
||||
if err:
|
||||
raise CartError(err)
|
||||
|
||||
|
||||
@@ -37,6 +37,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@transaction.atomic
|
||||
def build_invoice(invoice: Invoice) -> Invoice:
|
||||
invoice.locale = invoice.event.settings.get('invoice_language', invoice.event.settings.locale)
|
||||
if invoice.locale == '__user__':
|
||||
invoice.locale = invoice.order.locale or invoice.event.settings.locale
|
||||
|
||||
lp = invoice.order.payments.last()
|
||||
|
||||
with language(invoice.locale):
|
||||
@@ -85,6 +89,7 @@ def build_invoice(invoice: Invoice) -> Invoice:
|
||||
).split("\n") if a.strip()
|
||||
)
|
||||
invoice.internal_reference = ia.internal_reference
|
||||
invoice.custom_field = ia.custom_field
|
||||
invoice.invoice_to_company = ia.company
|
||||
invoice.invoice_to_name = ia.name
|
||||
invoice.invoice_to_street = ia.street
|
||||
@@ -249,17 +254,11 @@ def regenerate_invoice(invoice: Invoice):
|
||||
|
||||
|
||||
def generate_invoice(order: Order, trigger_pdf=True):
|
||||
locale = order.event.settings.get('invoice_language', order.event.settings.locale)
|
||||
if locale:
|
||||
if locale == '__user__':
|
||||
locale = order.locale or order.event.settings.locale
|
||||
|
||||
invoice = Invoice(
|
||||
order=order,
|
||||
event=order.event,
|
||||
organizer=order.event.organizer,
|
||||
date=timezone.now().date(),
|
||||
locale=locale
|
||||
)
|
||||
invoice = build_invoice(invoice)
|
||||
if trigger_pdf:
|
||||
@@ -313,7 +312,7 @@ def build_preview_invoice_pdf(event):
|
||||
|
||||
with rolledback_transaction(), language(locale):
|
||||
order = event.orders.create(status=Order.STATUS_PENDING, datetime=timezone.now(),
|
||||
expires=timezone.now(), code="PREVIEW", total=119)
|
||||
expires=timezone.now(), code="PREVIEW", total=100 * event.tax_rules.count())
|
||||
invoice = Invoice(
|
||||
order=order, event=event, invoice_no="PREVIEW",
|
||||
date=timezone.now().date(), locale=locale, organizer=event.organizer
|
||||
@@ -351,7 +350,7 @@ def build_preview_invoice_pdf(event):
|
||||
|
||||
if event.tax_rules.exists():
|
||||
for i, tr in enumerate(event.tax_rules.all()):
|
||||
tax = tr.tax(Decimal('100.00'))
|
||||
tax = tr.tax(Decimal('100.00'), base_price_is='gross')
|
||||
InvoiceLine.objects.create(
|
||||
invoice=invoice, description=_("Sample product {}").format(i + 1),
|
||||
gross_value=tax.gross, tax_value=tax.tax,
|
||||
|
||||
@@ -126,7 +126,7 @@ def mail(email: str, subject: str, template: Union[str, LazyI18nString],
|
||||
renderer = ClassicMailRenderer(None)
|
||||
content_plain = body_plain = render_mail(template, context)
|
||||
subject = str(subject).format_map(TolerantDict(context))
|
||||
sender = sender or (event.settings.get('mail_from') if event else settings.MAIL_FROM)
|
||||
sender = sender or (event.settings.get('mail_from') if event else settings.MAIL_FROM) or settings.MAIL_FROM
|
||||
if event:
|
||||
sender_name = event.settings.mail_from_name or str(event.name)
|
||||
sender = formataddr((sender_name, sender))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.conf import settings
|
||||
from django.template.loader import get_template
|
||||
from django.utils.timezone import override
|
||||
from django_scopes import scope, scopes_disabled
|
||||
from inlinestyler.utils import inline_css
|
||||
|
||||
@@ -79,7 +80,7 @@ def send_notification(logentry_id: int, action_type: str, user_id: int, method:
|
||||
if not notification_type:
|
||||
return # Ignore, e.g. plugin not active for this event
|
||||
|
||||
with language(user.locale):
|
||||
with language(user.locale), override(logentry.event.timezone if logentry.event else user.timezone):
|
||||
notification = notification_type.build_notification(logentry)
|
||||
|
||||
if method == "mail":
|
||||
|
||||
@@ -43,7 +43,11 @@ def parse_csv(file, length=None):
|
||||
if '\r' in data and '\n' not in data:
|
||||
data = data.replace('\r', '\n')
|
||||
|
||||
dialect = csv.Sniffer().sniff(data.split("\n")[0], delimiters=";,.#:")
|
||||
try:
|
||||
dialect = csv.Sniffer().sniff(data.split("\n")[0], delimiters=";,.#:")
|
||||
except csv.Error:
|
||||
return None
|
||||
|
||||
if dialect is None:
|
||||
return None
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
"""
|
||||
with transaction.atomic():
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
order = Order.objects.select_for_update().get(pk=order)
|
||||
if isinstance(user, int):
|
||||
user = User.objects.get(pk=user)
|
||||
if isinstance(api_token, int):
|
||||
@@ -294,8 +294,8 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
if not order.cancel_allowed():
|
||||
raise OrderError(_('You cannot cancel this order.'))
|
||||
invoices = []
|
||||
i = order.invoices.filter(is_cancellation=False, refered__isnull=True).last()
|
||||
if i:
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i and not i.refered.exists():
|
||||
invoices.append(generate_cancellation(i))
|
||||
|
||||
for position in order.positions.all():
|
||||
@@ -553,6 +553,8 @@ def _check_positions(event: Event, now_dt: datetime, positions: List[CartPositio
|
||||
bprice = bundle.designated_price or 0
|
||||
except ItemBundle.DoesNotExist:
|
||||
bprice = cp.price
|
||||
except ItemBundle.MultipleObjectsReturned:
|
||||
raise OrderError("Invalid product configuration (duplicate bundle)")
|
||||
price = get_price(cp.item, cp.variation, cp.voucher, bprice, cp.subevent, custom_price_is_net=False,
|
||||
invoice_address=address, force_custom_price=True, max_discount=max_discount)
|
||||
pbv = get_price(cp.item, cp.variation, None, bprice, cp.subevent, custom_price_is_net=False,
|
||||
@@ -1075,6 +1077,7 @@ class OrderChangeManager:
|
||||
AddOperation = namedtuple('AddOperation', ('item', 'variation', 'price', 'addon_to', 'subevent', 'seat'))
|
||||
SplitOperation = namedtuple('SplitOperation', ('position',))
|
||||
FeeValueOperation = namedtuple('FeeValueOperation', ('fee', 'value'))
|
||||
AddFeeOperation = namedtuple('AddFeeOperation', ('fee',))
|
||||
CancelFeeOperation = namedtuple('CancelFeeOperation', ('fee',))
|
||||
RegenerateSecretOperation = namedtuple('RegenerateSecretOperation', ('position',))
|
||||
|
||||
@@ -1188,6 +1191,11 @@ class OrderChangeManager:
|
||||
self._operations.append(self.CancelFeeOperation(fee))
|
||||
self._invoice_dirty = True
|
||||
|
||||
def add_fee(self, fee: OrderFee):
|
||||
self._totaldiff += fee.value
|
||||
self._invoice_dirty = True
|
||||
self._operations.append(self.AddFeeOperation(fee))
|
||||
|
||||
def change_fee(self, fee: OrderFee, value: Decimal):
|
||||
value = (fee.tax_rule or TaxRule.zero()).tax(value, base_price_is='gross')
|
||||
self._totaldiff += value.gross - fee.value
|
||||
@@ -1448,6 +1456,13 @@ class OrderChangeManager:
|
||||
invoice_address=self._invoice_address
|
||||
).gross
|
||||
)
|
||||
elif isinstance(op, self.AddFeeOperation):
|
||||
self.order.log_action('pretix.event.order.changed.addfee', user=self.user, auth=self.auth, data={
|
||||
'fee': op.fee.pk,
|
||||
})
|
||||
op.fee.order = self.order
|
||||
op.fee._calculate_tax()
|
||||
op.fee.save()
|
||||
elif isinstance(op, self.FeeValueOperation):
|
||||
self.order.log_action('pretix.event.order.changed.feevalue', user=self.user, auth=self.auth, data={
|
||||
'fee': op.fee.pk,
|
||||
@@ -1710,7 +1725,8 @@ class OrderChangeManager:
|
||||
i = self.order.invoices.filter(is_cancellation=False).last()
|
||||
if self.reissue_invoice and i and self._invoice_dirty:
|
||||
self._invoices.append(generate_cancellation(i))
|
||||
self._invoices.append(generate_invoice(self.order))
|
||||
if invoice_qualified(self.order):
|
||||
self._invoices.append(generate_invoice(self.order))
|
||||
|
||||
def _check_complete_cancel(self):
|
||||
current = self.order.positions.count()
|
||||
@@ -1800,6 +1816,61 @@ def perform_order(self, event: Event, payment_provider: str, positions: List[str
|
||||
raise OrderError(str(error_messages['busy']))
|
||||
|
||||
|
||||
def _try_auto_refund(order):
|
||||
notify_admin = False
|
||||
error = False
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
refund_amount = order.pending_sum * -1
|
||||
if refund_amount <= Decimal('0.00'):
|
||||
return
|
||||
|
||||
proposals = order.propose_auto_refunds(refund_amount)
|
||||
can_auto_refund = sum(proposals.values()) == refund_amount
|
||||
if can_auto_refund:
|
||||
for p, value in proposals.items():
|
||||
with transaction.atomic():
|
||||
r = order.refunds.create(
|
||||
payment=p,
|
||||
source=OrderRefund.REFUND_SOURCE_BUYER,
|
||||
state=OrderRefund.REFUND_STATE_CREATED,
|
||||
amount=value,
|
||||
provider=p.provider
|
||||
)
|
||||
order.log_action('pretix.event.order.refund.created', {
|
||||
'local_id': r.local_id,
|
||||
'provider': r.provider,
|
||||
})
|
||||
|
||||
try:
|
||||
r.payment_provider.execute_refund(r)
|
||||
except PaymentException as e:
|
||||
with transaction.atomic():
|
||||
r.state = OrderRefund.REFUND_STATE_FAILED
|
||||
r.save()
|
||||
order.log_action('pretix.event.order.refund.failed', {
|
||||
'local_id': r.local_id,
|
||||
'provider': r.provider,
|
||||
'error': str(e)
|
||||
})
|
||||
error = True
|
||||
notify_admin = True
|
||||
else:
|
||||
if r.state != OrderRefund.REFUND_STATE_DONE:
|
||||
notify_admin = True
|
||||
elif refund_amount != Decimal('0.00'):
|
||||
notify_admin = True
|
||||
|
||||
if notify_admin:
|
||||
order.log_action('pretix.event.order.refund.requested')
|
||||
if error:
|
||||
raise OrderError(
|
||||
_(
|
||||
'There was an error while trying to send the money back to you. Please contact the event organizer '
|
||||
'for further information.')
|
||||
)
|
||||
|
||||
|
||||
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
|
||||
@scopes_disabled()
|
||||
def cancel_order(self, order: int, user: int=None, send_mail: bool=True, api_token=None, oauth_application=None,
|
||||
@@ -1809,52 +1880,7 @@ def cancel_order(self, order: int, user: int=None, send_mail: bool=True, api_tok
|
||||
ret = _cancel_order(order, user, send_mail, api_token, device, oauth_application,
|
||||
cancellation_fee)
|
||||
if try_auto_refund:
|
||||
notify_admin = False
|
||||
error = False
|
||||
order = Order.objects.get(pk=order)
|
||||
refund_amount = order.pending_sum * -1
|
||||
proposals = order.propose_auto_refunds(refund_amount)
|
||||
can_auto_refund = sum(proposals.values()) == refund_amount
|
||||
if can_auto_refund:
|
||||
for p, value in proposals.items():
|
||||
with transaction.atomic():
|
||||
r = order.refunds.create(
|
||||
payment=p,
|
||||
source=OrderRefund.REFUND_SOURCE_BUYER,
|
||||
state=OrderRefund.REFUND_STATE_CREATED,
|
||||
amount=value,
|
||||
provider=p.provider
|
||||
)
|
||||
order.log_action('pretix.event.order.refund.created', {
|
||||
'local_id': r.local_id,
|
||||
'provider': r.provider,
|
||||
})
|
||||
|
||||
try:
|
||||
r.payment_provider.execute_refund(r)
|
||||
except PaymentException as e:
|
||||
with transaction.atomic():
|
||||
r.state = OrderRefund.REFUND_STATE_FAILED
|
||||
r.save()
|
||||
order.log_action('pretix.event.order.refund.failed', {
|
||||
'local_id': r.local_id,
|
||||
'provider': r.provider,
|
||||
'error': str(e)
|
||||
})
|
||||
error = True
|
||||
notify_admin = True
|
||||
else:
|
||||
if r.state != OrderRefund.REFUND_STATE_DONE:
|
||||
notify_admin = True
|
||||
elif refund_amount != Decimal('0.00'):
|
||||
notify_admin = True
|
||||
|
||||
if notify_admin:
|
||||
order.log_action('pretix.event.order.refund.requested')
|
||||
if error:
|
||||
raise OrderError(
|
||||
_('There was an error while trying to send the money back to you. Please contact the event organizer for further information.')
|
||||
)
|
||||
_try_auto_refund(order)
|
||||
return ret
|
||||
except LockTimeoutException:
|
||||
self.retry()
|
||||
|
||||
@@ -42,6 +42,8 @@ def assign_automatically(event: Event, user_id: int=None, subevent_id: int=None)
|
||||
continue
|
||||
if wle.subevent and not wle.subevent.presale_is_running:
|
||||
continue
|
||||
if not wle.item.active or (wle.variation and not wle.variation.active):
|
||||
continue
|
||||
|
||||
quotas = (wle.variation.quotas.filter(subevent=wle.subevent)
|
||||
if wle.variation
|
||||
|
||||
@@ -15,7 +15,7 @@ from django.utils.translation import (
|
||||
)
|
||||
from django_countries import countries
|
||||
from hierarkey.models import GlobalSettingsBase, Hierarkey
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput
|
||||
from i18nfield.strings import LazyI18nString
|
||||
from rest_framework import serializers
|
||||
|
||||
@@ -182,6 +182,20 @@ DEFAULTS = {
|
||||
required=False
|
||||
)
|
||||
},
|
||||
'invoice_address_custom_field': {
|
||||
'default': '',
|
||||
'type': LazyI18nString,
|
||||
'form_class': I18nFormField,
|
||||
'serializer_class': I18nField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Custom address field"),
|
||||
widget=I18nTextInput,
|
||||
help_text=_("If you want to add a custom text field, e.g. for a country-specific registration number, to "
|
||||
"your invoice address form, please fill in the label here. This label will both be used for "
|
||||
"asking the user to input their details as well as for displaying the value on the invoice. "
|
||||
"The field will not be required.")
|
||||
)
|
||||
},
|
||||
'invoice_address_vatid': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
@@ -337,6 +351,7 @@ DEFAULTS = {
|
||||
"you use slow payment methods like bank transfer, we recommend 14 days. If you only use real-time "
|
||||
"payment methods, we recommend still setting two or three days to allow people to retry failed "
|
||||
"payments."),
|
||||
required=True,
|
||||
validators=[MinValueValidator(0),
|
||||
MaxValueValidator(1000000)]
|
||||
),
|
||||
@@ -527,6 +542,7 @@ DEFAULTS = {
|
||||
'serializer_class': serializers.CharField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Domestic tax ID"),
|
||||
help_text=_("e.g. tax number in Germany, ABN in Australia, …")
|
||||
)
|
||||
},
|
||||
'invoice_address_from_vat_id': {
|
||||
@@ -1283,6 +1299,14 @@ Your {event} team"""))
|
||||
'default': '#D36060',
|
||||
'type': str
|
||||
},
|
||||
'theme_color_background': {
|
||||
'default': '#FFFFFF',
|
||||
'type': str
|
||||
},
|
||||
'theme_round_borders': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
},
|
||||
'primary_font': {
|
||||
'default': 'Open Sans',
|
||||
'type': str
|
||||
@@ -1307,6 +1331,22 @@ Your {event} team"""))
|
||||
'default': None,
|
||||
'type': File
|
||||
},
|
||||
'logo_image_large': {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
},
|
||||
'logo_show_title': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
},
|
||||
'organizer_logo_image': {
|
||||
'default': None,
|
||||
'type': File
|
||||
},
|
||||
'organizer_logo_image_large': {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
},
|
||||
'og_image': {
|
||||
'default': None,
|
||||
'type': File
|
||||
@@ -1733,7 +1773,7 @@ def validate_settings(event, settings_dict):
|
||||
})
|
||||
if settings_dict.get('invoice_address_company_required') and not settings_dict.get('invoice_address_required'):
|
||||
raise ValidationError({
|
||||
'invoice_address_company_requred': _('You have to require invoice addresses to require for company names.')
|
||||
'invoice_address_company_required': _('You have to require invoice addresses to require for company names.')
|
||||
})
|
||||
|
||||
payment_term_last = settings_dict.get('payment_term_last')
|
||||
|
||||
@@ -12,19 +12,23 @@ from django.utils.safestring import mark_safe
|
||||
|
||||
register = template.Library()
|
||||
|
||||
ALLOWED_TAGS = [
|
||||
ALLOWED_TAGS_SNIPPET = [
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'b',
|
||||
'blockquote',
|
||||
'br',
|
||||
'code',
|
||||
'em',
|
||||
'i',
|
||||
'strong',
|
||||
'span',
|
||||
# Update doc/user/markdown.rst if you change this!
|
||||
]
|
||||
ALLOWED_TAGS = ALLOWED_TAGS_SNIPPET + [
|
||||
'blockquote',
|
||||
'li',
|
||||
'ol',
|
||||
'strong',
|
||||
'ul',
|
||||
'p',
|
||||
'table',
|
||||
@@ -34,7 +38,6 @@ ALLOWED_TAGS = [
|
||||
'td',
|
||||
'th',
|
||||
'div',
|
||||
'span',
|
||||
'hr',
|
||||
'h1',
|
||||
'h2',
|
||||
@@ -95,7 +98,8 @@ def markdown_compile_email(source):
|
||||
), parse_email=True)
|
||||
|
||||
|
||||
def markdown_compile(source):
|
||||
def markdown_compile(source, snippet=False):
|
||||
tags = ALLOWED_TAGS_SNIPPET if snippet else ALLOWED_TAGS
|
||||
return bleach.clean(
|
||||
markdown.markdown(
|
||||
source,
|
||||
@@ -104,7 +108,8 @@ def markdown_compile(source):
|
||||
'markdown.extensions.nl2br'
|
||||
]
|
||||
),
|
||||
tags=ALLOWED_TAGS,
|
||||
strip=snippet,
|
||||
tags=tags,
|
||||
attributes=ALLOWED_ATTRIBUTES,
|
||||
protocols=ALLOWED_PROTOCOLS,
|
||||
)
|
||||
@@ -122,3 +127,17 @@ def rich_text(text: str, **kwargs):
|
||||
parse_email=True
|
||||
)
|
||||
return mark_safe(body_md)
|
||||
|
||||
|
||||
@register.filter
|
||||
def rich_text_snippet(text: str, **kwargs):
|
||||
"""
|
||||
Processes markdown and cleans HTML in a text input.
|
||||
"""
|
||||
text = str(text)
|
||||
body_md = bleach.linkify(
|
||||
markdown_compile(text, snippet=True),
|
||||
callbacks=DEFAULT_CALLBACKS + ([safelink_callback] if kwargs.get('safelinks', True) else [abslink_callback]),
|
||||
parse_email=True
|
||||
)
|
||||
return mark_safe(body_md)
|
||||
|
||||
@@ -355,11 +355,23 @@ class EventSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
)
|
||||
logo_image = ExtFileField(
|
||||
label=_('Logo image'),
|
||||
label=_('Header image'),
|
||||
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
|
||||
required=False,
|
||||
help_text=_('If you provide a logo image, we will by default not show your events name and date '
|
||||
'in the page header. We will show your logo with a maximal height of 120 pixels.')
|
||||
help_text=_('If you provide a logo image, we will by default not show your event name and date '
|
||||
'in the page header. By default, we show your logo with a size of up to 1140x120 pixels. You '
|
||||
'can increase the size with the setting below. We recommend not using small details on the picture '
|
||||
'as it will be resized on smaller screens.')
|
||||
)
|
||||
logo_image_large = forms.BooleanField(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
required=False,
|
||||
)
|
||||
logo_show_title = forms.BooleanField(
|
||||
label=_('Show event title even if a header image is present'),
|
||||
help_text=_('The title will only be shown on the event front page.'),
|
||||
required=False,
|
||||
)
|
||||
og_image = ExtFileField(
|
||||
label=_('Social media image'),
|
||||
@@ -399,6 +411,20 @@ class EventSettingsForm(SettingsForm):
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
primary_font = forms.ChoiceField(
|
||||
label=_('Font'),
|
||||
choices=[
|
||||
@@ -567,6 +593,7 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
'invoice_address_vatid',
|
||||
'invoice_address_company_required',
|
||||
'invoice_address_beneficiary',
|
||||
'invoice_address_custom_field',
|
||||
'invoice_name_required',
|
||||
'invoice_address_not_asked_free',
|
||||
'invoice_include_free',
|
||||
@@ -1202,3 +1229,11 @@ QuickSetupProductFormSet = formset_factory(
|
||||
formset=BaseQuickSetupProductFormSet,
|
||||
can_order=False, can_delete=True, extra=0
|
||||
)
|
||||
|
||||
|
||||
class ItemMetaPropertyForm(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = ['name', 'default']
|
||||
widgets = {
|
||||
'default': forms.TextInput()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from decimal import Decimal
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -18,7 +19,7 @@ from pretix.base.forms import I18nFormSet, I18nModelForm
|
||||
from pretix.base.models import (
|
||||
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
|
||||
)
|
||||
from pretix.base.models.items import ItemAddOn, ItemBundle
|
||||
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
|
||||
from pretix.base.signals import item_copy_data
|
||||
from pretix.control.forms import SplitDateTimeField, SplitDateTimePickerWidget
|
||||
from pretix.control.forms.widgets import Select2
|
||||
@@ -683,6 +684,27 @@ class ItemBundleFormSet(I18nFormSet):
|
||||
self.add_fields(form, None)
|
||||
return form
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
ivs = set()
|
||||
for i in range(0, self.total_form_count()):
|
||||
form = self.forms[i]
|
||||
if self.can_delete:
|
||||
if self._should_delete_form(form):
|
||||
# This form is going to be deleted so any of its errors
|
||||
# should not cause the entire formset to be invalid.
|
||||
try:
|
||||
ivs.remove(form.cleaned_data['itemvar'])
|
||||
except KeyError:
|
||||
pass
|
||||
continue
|
||||
|
||||
if 'itemvar' in form.cleaned_data:
|
||||
if form.cleaned_data['itemvar'] in ivs:
|
||||
raise ValidationError(_('You added the same bundled product twice'))
|
||||
|
||||
ivs.add(form.cleaned_data['itemvar'])
|
||||
|
||||
|
||||
class ItemBundleForm(I18nModelForm):
|
||||
itemvar = forms.ChoiceField(label=_('Bundled product'))
|
||||
@@ -756,3 +778,27 @@ class ItemBundleForm(I18nModelForm):
|
||||
'count',
|
||||
'designated_price',
|
||||
]
|
||||
|
||||
|
||||
class ItemMetaValueForm(forms.ModelForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.property = kwargs.pop('property')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['value'].required = False
|
||||
self.fields['value'].widget.attrs['placeholder'] = self.property.default
|
||||
self.fields['value'].widget.attrs['data-typeahead-url'] = (
|
||||
reverse('control:event.items.meta.typeahead', kwargs={
|
||||
'organizer': self.property.event.organizer.slug,
|
||||
'event': self.property.event.slug
|
||||
}) + '?' + urlencode({
|
||||
'property': self.property.name,
|
||||
})
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ItemMetaValue
|
||||
fields = ['value']
|
||||
widgets = {
|
||||
'value': forms.TextInput()
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from datetime import date, datetime, time
|
||||
from decimal import Decimal
|
||||
|
||||
from django import forms
|
||||
@@ -5,8 +6,12 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
from django.utils.timezone import make_aware, now
|
||||
from django.utils.translation import (
|
||||
gettext_noop, pgettext_lazy, ugettext_lazy as _,
|
||||
)
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.base.email import get_available_placeholders
|
||||
from pretix.base.forms import I18nModelForm, PlaceholderValidator
|
||||
@@ -25,16 +30,17 @@ class ExtendForm(I18nModelForm):
|
||||
'and you having sold more tickets than you planned!'),
|
||||
required=False
|
||||
)
|
||||
expires = forms.DateField(
|
||||
label=_("Expiration date"),
|
||||
widget=forms.DateInput(attrs={
|
||||
'class': 'datepickerfield',
|
||||
'data-is-payment-date': 'true'
|
||||
}),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ['expires']
|
||||
widgets = {
|
||||
'expires': forms.DateInput(attrs={
|
||||
'class': 'datepickerfield',
|
||||
'data-is-payment-date': 'true'
|
||||
})
|
||||
}
|
||||
fields = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -45,11 +51,22 @@ class ExtendForm(I18nModelForm):
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
data['expires'] = data['expires'].replace(hour=23, minute=59, second=59)
|
||||
if data['expires'] < now():
|
||||
raise ValidationError(_('The new expiry date needs to be in the future.'))
|
||||
if data.get('expires'):
|
||||
if isinstance(data['expires'], date):
|
||||
data['expires'] = make_aware(datetime.combine(
|
||||
data['expires'],
|
||||
time(hour=23, minute=59, second=59)
|
||||
), self.instance.event.timezone)
|
||||
else:
|
||||
data['expires'] = data['expires'].replace(hour=23, minute=59, second=59)
|
||||
if data['expires'] < now():
|
||||
raise ValidationError(_('The new expiry date needs to be in the future.'))
|
||||
return data
|
||||
|
||||
def save(self, commit=True):
|
||||
self.instance.expires = self.cleaned_data['expires']
|
||||
return super().save(commit)
|
||||
|
||||
|
||||
class ConfirmPaymentForm(forms.Form):
|
||||
force = forms.BooleanField(
|
||||
@@ -501,3 +518,127 @@ class OrderRefundForm(forms.Form):
|
||||
if data.get('mode') == 'partial' and not data.get('partial_amount'):
|
||||
raise ValidationError(_('You need to specify an amount for a partial refund.'))
|
||||
return data
|
||||
|
||||
|
||||
class EventCancelForm(forms.Form):
|
||||
subevent = forms.ModelChoiceField(
|
||||
SubEvent.objects.none(),
|
||||
label=pgettext_lazy('subevent', 'Date'),
|
||||
required=True,
|
||||
empty_label=None
|
||||
)
|
||||
auto_refund = forms.BooleanField(
|
||||
label=_('Automatically refund money if possible'),
|
||||
initial=True,
|
||||
required=False
|
||||
)
|
||||
keep_fee_fixed = forms.DecimalField(
|
||||
label=_("Keep a fixed cancellation fee"),
|
||||
max_digits=10, decimal_places=2,
|
||||
required=False
|
||||
)
|
||||
keep_fee_percentage = forms.DecimalField(
|
||||
label=_("Keep a percentual cancellation fee"),
|
||||
max_digits=10, decimal_places=2,
|
||||
required=False
|
||||
)
|
||||
keep_fees = forms.BooleanField(
|
||||
label=_("Keep payment, shipping and service fees"),
|
||||
required=False,
|
||||
)
|
||||
send = forms.BooleanField(
|
||||
label=_("Send information via email"),
|
||||
required=False
|
||||
)
|
||||
send_subject = forms.CharField()
|
||||
send_message = forms.CharField()
|
||||
send_waitinglist = forms.BooleanField(
|
||||
label=_("Send information to waiting list"),
|
||||
required=False
|
||||
)
|
||||
send_waitinglist_subject = forms.CharField()
|
||||
send_waitinglist_message = forms.CharField()
|
||||
|
||||
def _set_field_placeholders(self, fn, base_parameters):
|
||||
phs = [
|
||||
'{%s}' % p
|
||||
for p in sorted(get_available_placeholders(self.event, base_parameters).keys())
|
||||
]
|
||||
ht = _('Available placeholders: {list}').format(
|
||||
list=', '.join(phs)
|
||||
)
|
||||
if self.fields[fn].help_text:
|
||||
self.fields[fn].help_text += ' ' + str(ht)
|
||||
else:
|
||||
self.fields[fn].help_text = ht
|
||||
self.fields[fn].validators.append(
|
||||
PlaceholderValidator(phs)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['send_subject'] = I18nFormField(
|
||||
label=_("Subject"),
|
||||
required=True,
|
||||
initial=_('Canceled: {event}'),
|
||||
widget=I18nTextInput,
|
||||
locales=self.event.settings.get('locales'),
|
||||
)
|
||||
self.fields['send_message'] = I18nFormField(
|
||||
label=_('Message'),
|
||||
widget=I18nTextarea,
|
||||
required=True,
|
||||
locales=self.event.settings.get('locales'),
|
||||
initial=LazyI18nString.from_gettext(gettext_noop(
|
||||
'Hello,\n\n'
|
||||
'with this email, we regret to inform you that {event} has been canceled.\n\n'
|
||||
'We will refund you {refund_amount} to your original payment method.\n\n'
|
||||
'You can view the current state of your order here:\n\n{url}\n\nBest regards,\n\n'
|
||||
'Your {event} team'
|
||||
))
|
||||
)
|
||||
self._set_field_placeholders('send_subject', ['event_or_subevent', 'refund_amount', 'position_or_address',
|
||||
'order', 'event'])
|
||||
self._set_field_placeholders('send_message', ['event_or_subevent', 'refund_amount', 'position_or_address',
|
||||
'order', 'event'])
|
||||
self.fields['send_waitinglist_subject'] = I18nFormField(
|
||||
label=_("Subject"),
|
||||
required=True,
|
||||
initial=_('Canceled: {event}'),
|
||||
widget=I18nTextInput,
|
||||
locales=self.event.settings.get('locales'),
|
||||
)
|
||||
self.fields['send_waitinglist_message'] = I18nFormField(
|
||||
label=_('Message'),
|
||||
widget=I18nTextarea,
|
||||
required=True,
|
||||
locales=self.event.settings.get('locales'),
|
||||
initial=LazyI18nString.from_gettext(gettext_noop(
|
||||
'Hello,\n\n'
|
||||
'with this email, we regret to inform you that {event} has been canceled.\n\n'
|
||||
'You will therefore not receive a ticket from the waiting list.\n\n'
|
||||
'Best regards,\n\n'
|
||||
'Your {event} team'
|
||||
))
|
||||
)
|
||||
self._set_field_placeholders('send_waitinglist_subject', ['event_or_subevent', 'event'])
|
||||
self._set_field_placeholders('send_waitinglist_message', ['event_or_subevent', 'event'])
|
||||
|
||||
if self.event.has_subevents:
|
||||
self.fields['subevent'].queryset = self.event.subevents.all()
|
||||
self.fields['subevent'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'event',
|
||||
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
|
||||
'event': self.event.slug,
|
||||
'organizer': self.event.organizer.slug,
|
||||
}),
|
||||
'data-placeholder': pgettext_lazy('subevent', 'Date')
|
||||
}
|
||||
)
|
||||
self.fields['subevent'].widget.choices = self.fields['subevent'].choices
|
||||
self.fields['subevent'].required = True
|
||||
else:
|
||||
del self.fields['subevent']
|
||||
change_decimal_field(self.fields['keep_fee_fixed'], self.event.currency)
|
||||
|
||||
@@ -250,6 +250,20 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
organizer_homepage_text = I18nFormField(
|
||||
label=_('Homepage text'),
|
||||
required=False,
|
||||
@@ -257,11 +271,18 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
help_text=_('This will be displayed on the organizer homepage.')
|
||||
)
|
||||
organizer_logo_image = ExtFileField(
|
||||
label=_('Logo image'),
|
||||
label=_('Header image'),
|
||||
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
|
||||
required=False,
|
||||
help_text=_('If you provide a logo image, we will by default not show your organization name '
|
||||
'in the page header. We will show your logo with a maximal height of 120 pixels.')
|
||||
'in the page header. By default, we show your logo with a size of up to 1140x120 pixels. You '
|
||||
'can increase the size with the setting below. We recommend not using small details on the picture '
|
||||
'as it will be resized on smaller screens.')
|
||||
)
|
||||
organizer_logo_image_large = forms.BooleanField(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
required=False,
|
||||
)
|
||||
event_list_type = forms.ChoiceField(
|
||||
label=_('Default overview style'),
|
||||
|
||||
@@ -65,6 +65,8 @@ def _display_order_changed(event: Event, logentry: LogEntry):
|
||||
old_price=money_filter(Decimal(data['old_price']), event.currency),
|
||||
new_price=money_filter(Decimal(data['new_price']), event.currency),
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.addfee':
|
||||
return text + ' ' + str(_('A fee has been added'))
|
||||
elif logentry.action_type == 'pretix.event.order.changed.feevalue':
|
||||
return text + ' ' + _('A fee was changed from {old_price} to {new_price}.').format(
|
||||
old_price=money_filter(Decimal(data['old_price']), event.currency),
|
||||
@@ -180,6 +182,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
plains = {
|
||||
'pretix.object.cloned': _('This object has been created by cloning.'),
|
||||
'pretix.event.comment': _('The event\'s internal comment has been updated.'),
|
||||
'pretix.event.canceled': _('The event has been canceled.'),
|
||||
'pretix.event.order.modified': _('The order details have been changed.'),
|
||||
'pretix.event.order.unpaid': _('The order has been marked as unpaid.'),
|
||||
'pretix.event.order.secret.changed': _('The order\'s secret has been changed.'),
|
||||
@@ -213,6 +216,8 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.order.email.expire_warning_sent': _('An email has been sent with a warning that the order is about '
|
||||
'to expire.'),
|
||||
'pretix.event.order.email.order_canceled': _('An email has been sent to notify the user that the order has been canceled.'),
|
||||
'pretix.event.order.email.event_canceled': _('An email has been sent to notify the user that the event has '
|
||||
'been canceled.'),
|
||||
'pretix.event.order.email.order_changed': _('An email has been sent to notify the user that the order has been changed.'),
|
||||
'pretix.event.order.email.order_free': _('An email has been sent to notify the user that the order has been received.'),
|
||||
'pretix.event.order.email.order_paid': _('An email has been sent to notify the user that payment has been received.'),
|
||||
@@ -314,6 +319,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.team.changed': _('The team settings have been changed.'),
|
||||
'pretix.team.deleted': _('The team has been deleted.'),
|
||||
'pretix.subevent.deleted': pgettext_lazy('subevent', 'The event date has been deleted.'),
|
||||
'pretix.subevent.canceled': pgettext_lazy('subevent', 'The event date has been canceled.'),
|
||||
'pretix.subevent.changed': pgettext_lazy('subevent', 'The event date has been changed.'),
|
||||
'pretix.subevent.added': pgettext_lazy('subevent', 'The event date has been created.'),
|
||||
'pretix.subevent.quota.added': pgettext_lazy('subevent', 'A quota has been added to the event date.'),
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
</div>
|
||||
<h2>{% trans "Your upcoming events" %}</h2>
|
||||
<div class="dashboard">
|
||||
<div class="widget-small widget-container">
|
||||
<a href="{% url "control:events.add" %}" class="widget">
|
||||
<div class="newevent"><span class="fa fa-plus-circle"></span>{% trans "Create a new event" %}</div>
|
||||
</a>
|
||||
</div>
|
||||
{% if can_create_event %}
|
||||
<div class="widget-small widget-container">
|
||||
<a href="{% url "control:events.add" %}" class="widget">
|
||||
<div class="newevent"><span class="fa fa-plus-circle"></span>{% trans "Create a new event" %}</div>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for w in upcoming %}
|
||||
<div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }} {% if w.lazy %}widget-lazy-loading{% endif %}" data-lazy-id="{{ w.lazy }}">
|
||||
<div class="widget">
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Cancel or delete event" %}</h1>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Go offline" %}</h3>
|
||||
</div>
|
||||
<div class="row panel-body">
|
||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
||||
{% blocktrans trimmed %}
|
||||
You can take your event offline. Nobody except your team will be able to see or access it any more.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<form action="{% url "control:event.live" event=request.event.slug organizer=request.organizer.slug %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="live" value="false">
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-lg btn-block">
|
||||
<span class="fa fa-power-off"></span>
|
||||
{% trans "Go offline" %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Cancel event" %}</h3>
|
||||
</div>
|
||||
<div class="row panel-body">
|
||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
||||
{% blocktrans trimmed %}
|
||||
If you need to call of your event you want to cancel and refund all tickets, you can do so through
|
||||
this option.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<a href="{% url "control:event.cancel" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-danger btn-block btn-lg">
|
||||
<span class="fa fa-ban"></span>
|
||||
{% trans "Cancel event" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Delete personal data" %}</h3>
|
||||
</div>
|
||||
<div class="row panel-body">
|
||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
||||
{% blocktrans trimmed %}
|
||||
You can remove personal data such as names and email addresses from your event and only retain the
|
||||
finanical information such as the number and type of ticekts sold.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<a href="
|
||||
{% url "control:event.shredder.start" event=request.event.slug organizer=request.organizer.slug %}" class="btn btn-danger btn-lg btn-block">
|
||||
<span class="fa fa-eraser"></span>
|
||||
{% trans "Delete personal data" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Delete event" %}</h3>
|
||||
</div>
|
||||
<div class="row panel-body">
|
||||
<div class="col-sm-12 col-md-9 nomargin-bottom">
|
||||
{% blocktrans trimmed %}
|
||||
You can delete your event completely only as long as it does not contain any undeletable data, such as
|
||||
orders not performed in test mode.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<a href="{% url "control:event.delete" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-danger btn-block btn-lg {% if not request.event.allow_delete %}disabled{% endif %}">
|
||||
<span class="fa fa-trash"></span>
|
||||
{% trans "Delete event" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -29,6 +29,7 @@
|
||||
{% bootstrap_field form.invoice_address_vatid layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_beneficiary layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_not_asked_free layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_custom_field layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Issuer details" %}</legend>
|
||||
|
||||
@@ -112,4 +112,11 @@
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<a href="{% url "control:event.dangerzone" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-default btn-lg">
|
||||
<span class="fa fa-trash"></span>
|
||||
{% trans "Cancel or delete event" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
{% load hierarkey_form %}
|
||||
{% load formset_tags %}
|
||||
{% block custom_header %}
|
||||
{{ block.super }}
|
||||
<link type="text/css" rel="stylesheet" href="{% url "control:pdf.css" %}">
|
||||
@@ -97,12 +98,16 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Shop design" %}</legend>
|
||||
{% bootstrap_field sform.logo_image layout="control" %}
|
||||
{% bootstrap_field sform.logo_image_large layout="control" %}
|
||||
{% bootstrap_field sform.logo_show_title layout="control" %}
|
||||
{% bootstrap_field sform.og_image layout="control" %}
|
||||
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
|
||||
{% propagated request.event org_url "primary_color" "primary_font" "theme_color_success" "theme_color_danger" %}
|
||||
{% bootstrap_field sform.primary_color layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_success layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_danger layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_background layout="control" %}
|
||||
{% bootstrap_field sform.theme_round_borders layout="control" %}
|
||||
{% bootstrap_field sform.primary_font layout="control" %}
|
||||
{% endpropagated %}
|
||||
</fieldset>
|
||||
@@ -139,21 +144,75 @@
|
||||
{% bootstrap_field sform.waiting_list_auto layout="control" %}
|
||||
{% bootstrap_field sform.waiting_list_hours layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Item metadata" %}</legend>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You can here define a set of metadata properties (i.e. variables) that you can later set for your
|
||||
items and re-use in places like ticket layouts. This is an useful timesaver if you create lots and
|
||||
lots of items.
|
||||
{% 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="row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_field form.name layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5 col-lg-6">
|
||||
{% bootstrap_field form.default layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 col-lg-1 text-right flip">
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="row" 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="col-md-5">
|
||||
{% bootstrap_field formset.empty_form.name layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5 col-lg-6">
|
||||
{% bootstrap_field formset.empty_form.default layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 col-lg-1 text-right flip">
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default" data-formset-add>
|
||||
<i class="fa fa-plus"></i> {% trans "Add property" %}</button>
|
||||
</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<div class="pull-left">
|
||||
<a href="{% url "control:event.delete" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
class="btn {% if request.event.allow_delete %}{% endif %} btn-danger btn-lg">
|
||||
<span class="fa fa-trash"></span>
|
||||
{% trans "Delete event" %}
|
||||
</a>
|
||||
<a href="{% url "control:event.shredder.start" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
<a href="{% url "control:event.dangerzone" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-danger btn-lg">
|
||||
<span class="fa fa-eraser"></span>
|
||||
{% trans "Delete personal data" %}
|
||||
<span class="fa fa-trash"></span>
|
||||
{% trans "Cancel or delete event" %}
|
||||
</a>
|
||||
<a href="{% url "control:events.add" %}?clone={{ request.event.pk }}"
|
||||
class="btn btn-default btn-lg">
|
||||
|
||||
@@ -20,6 +20,26 @@
|
||||
{% bootstrap_field form.description layout="control" %}
|
||||
{% bootstrap_field form.picture layout="control" %}
|
||||
{% bootstrap_field form.require_approval layout="control" %}
|
||||
|
||||
{% if meta_forms %}
|
||||
<div class="form-group metadata-group">
|
||||
<label class="col-md-3 control-label">{% trans "Meta data" %}</label>
|
||||
<div class="col-md-9">
|
||||
{% for form in meta_forms %}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label for="{{ form.value.id_for_label }}">
|
||||
{{ form.property.name }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
{% bootstrap_form form layout="inline" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Price" %}</legend>
|
||||
|
||||
@@ -734,6 +734,10 @@
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if request.event.settings.invoice_address_custom_field and order.invoice_address.custom_field %}
|
||||
<dt>{{ request.event.settings.invoice_address_custom_field }}</dt>
|
||||
<dd>{{ order.invoice_address.custom_field }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Internal reference" %}</dt>
|
||||
<dd>{{ order.invoice_address.internal_reference }}</dd>
|
||||
</dl>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load eventsignal %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Cancel event" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Cancel event" %}</h1>
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed %}
|
||||
You can use this page to cancel and refund all orders at once in case you need to call of your event.
|
||||
This will also disable all products so no new orders can be created. Make sure that you check afterwards
|
||||
for any overpaid orders or pending refunds that you need to take care of manually.
|
||||
{% endblocktrans %}
|
||||
<br><br>
|
||||
{% blocktrans trimmed %}
|
||||
After starting this operation, depending on the size of your event, it might take a few minutes or longer
|
||||
until all orders are processed.
|
||||
{% endblocktrans %}
|
||||
<br><br>
|
||||
<strong>
|
||||
{% trans "All actions performed on this page are irreversible. If in doubt, please contact support before using it." %}
|
||||
</strong>
|
||||
</div>
|
||||
<form action="" method="post" class="form-horizontal" data-asynctask data-asynctask-download data-asynctask-long>
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% if request.event.has_subevents %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Select date" context "subevents" %}</legend>
|
||||
{% bootstrap_field form.subevent layout="control" %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Refund options" %}</legend>
|
||||
{% bootstrap_field form.auto_refund layout="control" %}
|
||||
{% bootstrap_field form.keep_fee_fixed layout="control" %}
|
||||
{% bootstrap_field form.keep_fee_percentage layout="control" %}
|
||||
{% bootstrap_field form.keep_fees layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Send out emails" %}</legend>
|
||||
{% bootstrap_field form.send layout="control" %}
|
||||
{% bootstrap_field form.send_subject layout="horizontal" %}
|
||||
{% bootstrap_field form.send_message layout="horizontal" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Waiting list" %}</legend>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Your waiting list will not be deleted automatically, but it will receive no new tickets due to the
|
||||
products being disabled. You can choose to inform people on the waiting list by using this option.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
<strong>
|
||||
{% blocktrans trimmed %}
|
||||
You should not execute this function multiple times for the same event, or everyone on the
|
||||
waiting list will get multiple emails.
|
||||
{% endblocktrans %}
|
||||
</strong>
|
||||
</p>
|
||||
{% bootstrap_field form.send_waitinglist layout="control" %}
|
||||
{% bootstrap_field form.send_waitinglist_subject layout="horizontal" %}
|
||||
{% bootstrap_field form.send_waitinglist_message layout="horizontal" %}
|
||||
</fieldset>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-danger btn-save">
|
||||
{% trans "Cancel all orders" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -37,6 +37,7 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Organizer page" %}</legend>
|
||||
{% bootstrap_field sform.organizer_logo_image layout="control" %}
|
||||
{% bootstrap_field sform.organizer_logo_image_large layout="control" %}
|
||||
{% bootstrap_field sform.organizer_homepage_text layout="control" %}
|
||||
{% bootstrap_field sform.event_list_type layout="control" %}
|
||||
{% bootstrap_field sform.event_list_availability layout="control" %}
|
||||
@@ -57,6 +58,8 @@
|
||||
{% bootstrap_field sform.primary_color layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_success layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_danger layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_background layout="control" %}
|
||||
{% bootstrap_field sform.theme_round_borders layout="control" %}
|
||||
{% bootstrap_field sform.primary_font layout="control" %}
|
||||
{% bootstrap_field sform.favicon layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -45,50 +45,53 @@
|
||||
{% trans "Transactions" %}
|
||||
</h3>
|
||||
</div>
|
||||
<table class="panel-body table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Order" %}</th>
|
||||
<th class="text-right">{% trans "Value" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for t in card.transactions.all %}
|
||||
<form class="" method="post" action="">
|
||||
{% csrf_token %}
|
||||
<table class="panel-body table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{ t.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>
|
||||
{% if t.order %}
|
||||
<a href="{% url "control:event.order" event=t.order.event.slug organizer=t.order.event.organizer.slug code=t.order.code %}">
|
||||
{{ t.order.full_code }}
|
||||
</a>
|
||||
{% else %}
|
||||
<em>{% trans "Manual transaction" %}</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ t.value|money:card.currency }}
|
||||
</td>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Order" %}</th>
|
||||
<th class="text-right">{% trans "Value" %}</th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-right">
|
||||
<form class="helper-display-inline form-inline" method="post" action="">
|
||||
{% csrf_token %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for t in card.transactions.all %}
|
||||
<tr>
|
||||
<td>{{ t.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>
|
||||
{% if t.order %}
|
||||
<a href="{% url "control:event.order" event=t.order.event.slug organizer=t.order.event.organizer.slug code=t.order.code %}">
|
||||
{{ t.order.full_code }}
|
||||
</a>
|
||||
{% else %}
|
||||
<em>{% trans "Manual transaction" %}{% if t.text %}: {{ t.text }}{% endif %}</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ t.value|money:card.currency }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="text" class="form-control helper-display-block" placeholder="{% trans "Text" %}"
|
||||
name="text">
|
||||
</td>
|
||||
<td class="text-right form-inline">
|
||||
<input type="text" class="form-control input-sm" placeholder="{% trans "Value" %}" name="value">
|
||||
<button class="btn btn-primary">
|
||||
<span class="fa fa-plus"></span>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 col-xs-12">
|
||||
|
||||
@@ -344,6 +344,11 @@
|
||||
{% trans "Event attribute:" %} {{ p.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for p in request.event.item_meta_properties.all %}
|
||||
<option value="itemmeta:{{ p.name }}">
|
||||
{% trans "Item attribute:" %} {{ p.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
<option value="other">{% trans "Other…" %}</option>
|
||||
</select>
|
||||
<textarea type="text" value="" class="input-block-level form-control"
|
||||
|
||||
@@ -159,6 +159,7 @@ urlpatterns = [
|
||||
url(r'^items/(?P<item>\d+)/up$', item.item_move_up, name='event.items.up'),
|
||||
url(r'^items/(?P<item>\d+)/down$', item.item_move_down, name='event.items.down'),
|
||||
url(r'^items/(?P<item>\d+)/delete$', item.ItemDelete.as_view(), name='event.items.delete'),
|
||||
url(r'^items/typeahead/meta/$', typeahead.item_meta_values, name='event.items.meta.typeahead'),
|
||||
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||
url(r'^categories/select2$', typeahead.category_select2, name='event.items.categories.select2'),
|
||||
url(r'^categories/(?P<category>\d+)/delete$', item.CategoryDelete.as_view(),
|
||||
@@ -264,6 +265,8 @@ urlpatterns = [
|
||||
url(r'^orders/refunds/$', orders.RefundList.as_view(), name='event.orders.refunds'),
|
||||
url(r'^orders/go$', orders.OrderGo.as_view(), name='event.orders.go'),
|
||||
url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
|
||||
url(r'^dangerzone/$', event.DangerZone.as_view(), name='event.dangerzone'),
|
||||
url(r'^cancel/$', orders.EventCancel.as_view(), name='event.cancel'),
|
||||
url(r'^shredder/$', shredder.StartShredView.as_view(), name='event.shredder.start'),
|
||||
url(r'^shredder/export$', shredder.ShredExportView.as_view(), name='event.shredder.export'),
|
||||
url(r'^shredder/download/(?P<file>[^/]+)/$', shredder.ShredDownloadView.as_view(), name='event.shredder.download'),
|
||||
|
||||
@@ -2,9 +2,11 @@ from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import (
|
||||
Count, Exists, IntegerField, Max, Min, OuterRef, Q, Subquery, Sum,
|
||||
Count, Exists, IntegerField, Max, Min, OuterRef, Prefetch, Q, Subquery,
|
||||
Sum,
|
||||
)
|
||||
from django.db.models.functions import Coalesce, Greatest
|
||||
from django.dispatch import receiver
|
||||
@@ -20,8 +22,8 @@ from django.utils.translation import pgettext, ugettext_lazy as _, ungettext
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import (
|
||||
Item, Order, OrderPosition, OrderRefund, RequiredAction, SubEvent, Voucher,
|
||||
WaitingListEntry,
|
||||
Item, ItemVariation, Order, OrderPosition, OrderRefund, RequiredAction,
|
||||
SubEvent, Voucher, WaitingListEntry,
|
||||
)
|
||||
from pretix.base.timeline import timeline_for_event
|
||||
from pretix.control.forms.event import CommentForm
|
||||
@@ -122,26 +124,50 @@ def waitinglist_widgets(sender, subevent=None, lazy=False, **kwargs):
|
||||
widgets = []
|
||||
|
||||
wles = WaitingListEntry.objects.filter(event=sender, subevent=subevent, voucher__isnull=True)
|
||||
if wles.count():
|
||||
if wles.exists():
|
||||
if not lazy:
|
||||
quota_cache = {}
|
||||
itemvar_cache = {}
|
||||
happy = 0
|
||||
tuples = wles.values('item', 'variation').order_by().annotate(cnt=Count('id'))
|
||||
|
||||
for wle in wles:
|
||||
if (wle.item, wle.variation) not in itemvar_cache:
|
||||
itemvar_cache[(wle.item, wle.variation)] = (
|
||||
wle.variation.check_quotas(subevent=wle.subevent, count_waitinglist=False, _cache=quota_cache)
|
||||
if wle.variation
|
||||
else wle.item.check_quotas(subevent=wle.subevent, count_waitinglist=False, _cache=quota_cache)
|
||||
)
|
||||
row = itemvar_cache.get((wle.item, wle.variation))
|
||||
items = {
|
||||
i.pk: i for i in sender.items.filter(id__in=[t['item'] for t in tuples]).prefetch_related(
|
||||
Prefetch('quotas',
|
||||
to_attr='_subevent_quotas',
|
||||
queryset=sender.quotas.using(settings.DATABASE_REPLICA).filter(subevent=subevent)),
|
||||
)
|
||||
}
|
||||
vars = {
|
||||
i.pk: i for i in ItemVariation.objects.filter(
|
||||
item__event=sender, id__in=[t['variation'] for t in tuples if t['variation']]
|
||||
).prefetch_related(
|
||||
Prefetch('quotas',
|
||||
to_attr='_subevent_quotas',
|
||||
queryset=sender.quotas.using(settings.DATABASE_REPLICA).filter(subevent=subevent)),
|
||||
)
|
||||
}
|
||||
|
||||
for wlt in tuples:
|
||||
item = items.get(wlt['item'])
|
||||
variation = vars.get(wlt['variation'])
|
||||
if not item:
|
||||
continue
|
||||
quotas = (
|
||||
variation._get_quotas(subevent=subevent)
|
||||
if variation
|
||||
else item._get_quotas(subevent=subevent)
|
||||
)
|
||||
row = (
|
||||
variation.check_quotas(subevent=subevent, count_waitinglist=False, _cache=quota_cache)
|
||||
if variation
|
||||
else item.check_quotas(subevent=subevent, count_waitinglist=False, _cache=quota_cache)
|
||||
)
|
||||
if row[1] is None:
|
||||
itemvar_cache[(wle.item, wle.variation)] = (row[0], row[1])
|
||||
happy += 1
|
||||
elif row[1] > 0:
|
||||
itemvar_cache[(wle.item, wle.variation)] = (row[0], row[1] - 1)
|
||||
happy += 1
|
||||
for q in quotas:
|
||||
quota_cache[q.pk] = (quota_cache[q.pk][0], quota_cache[q.pk][1] - 1)
|
||||
|
||||
widgets.append({
|
||||
'content': None if lazy else NUM_WIDGET.format(
|
||||
@@ -535,6 +561,7 @@ def user_index(request):
|
||||
|
||||
ctx = {
|
||||
'widgets': rearrange(widgets),
|
||||
'can_create_event': request.user.teams.filter(can_create_events=True).exists(),
|
||||
'upcoming': widgets_for_event_qs(
|
||||
request,
|
||||
annotated_event_query(request, lazy=True).filter(
|
||||
|
||||
@@ -11,6 +11,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files import File
|
||||
from django.db import transaction
|
||||
from django.db.models import ProtectedError
|
||||
from django.forms import inlineformset_factory
|
||||
from django.http import (
|
||||
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed,
|
||||
JsonResponse,
|
||||
@@ -39,9 +40,9 @@ from pretix.base.signals import register_ticket_outputs
|
||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||
from pretix.control.forms.event import (
|
||||
CancelSettingsForm, CommentForm, EventDeleteForm, EventMetaValueForm,
|
||||
EventSettingsForm, EventUpdateForm, InvoiceSettingsForm, MailSettingsForm,
|
||||
PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
||||
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
||||
EventSettingsForm, EventUpdateForm, InvoiceSettingsForm,
|
||||
ItemMetaPropertyForm, MailSettingsForm, PaymentSettingsForm, ProviderForm,
|
||||
QuickSetupForm, QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
||||
TicketSettingsForm, WidgetCodeForm,
|
||||
)
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
@@ -51,6 +52,7 @@ from pretix.multidomain.urlreverse import get_domain
|
||||
from pretix.plugins.stripe.payment import StripeSettingsHolder
|
||||
from pretix.presale.style import regenerate_css
|
||||
|
||||
from ...base.models.items import ItemMetaProperty
|
||||
from ..logdisplay import OVERVIEW_BANLIST
|
||||
from . import CreateView, PaginationMixin, UpdateView
|
||||
|
||||
@@ -137,6 +139,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['sform'] = self.sform
|
||||
context['meta_forms'] = self.meta_forms
|
||||
context['formset'] = self.formset
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
@@ -144,6 +147,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
self._save_decoupled(self.sform)
|
||||
self.sform.save()
|
||||
self.save_meta()
|
||||
self.save_formset(self.object)
|
||||
change_css = False
|
||||
|
||||
if self.sform.has_changed():
|
||||
@@ -152,6 +156,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
})
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders',
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
@@ -183,7 +188,8 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]):
|
||||
if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]) and \
|
||||
self.formset.is_valid():
|
||||
# reset timezone
|
||||
zone = timezone(self.sform.cleaned_data['timezone'])
|
||||
event = form.instance
|
||||
@@ -200,6 +206,33 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
def reset_timezone(tz, dt):
|
||||
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
|
||||
|
||||
@cached_property
|
||||
def formset(self):
|
||||
formsetclass = inlineformset_factory(
|
||||
Event, ItemMetaProperty,
|
||||
form=ItemMetaPropertyForm, can_order=False, can_delete=True, extra=0
|
||||
)
|
||||
return formsetclass(self.request.POST if self.request.method == "POST" else None,
|
||||
instance=self.object, queryset=self.object.item_meta_properties.all())
|
||||
|
||||
def save_formset(self, obj):
|
||||
for form in self.formset.initial_forms:
|
||||
if form in self.formset.deleted_forms:
|
||||
if not form.instance.pk:
|
||||
continue
|
||||
form.instance.delete()
|
||||
form.instance.pk = None
|
||||
elif form.has_changed():
|
||||
form.save()
|
||||
|
||||
for form in self.formset.extra_forms:
|
||||
if not form.has_changed():
|
||||
continue
|
||||
if self.formset._should_delete_form(form):
|
||||
continue
|
||||
form.instance.event = obj
|
||||
form.save()
|
||||
|
||||
|
||||
class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
||||
model = Event
|
||||
@@ -497,6 +530,11 @@ class InvoicePreview(EventPermissionRequiredMixin, View):
|
||||
return resp
|
||||
|
||||
|
||||
class DangerZone(EventPermissionRequiredMixin, TemplateView):
|
||||
permission = 'can_change_event_settings'
|
||||
template_name = 'pretixcontrol/event/dangerzone.html'
|
||||
|
||||
|
||||
class DisplaySettings(View):
|
||||
def get(self, request, *wargs, **kwargs):
|
||||
return redirect(reverse('control:event.settings', kwargs={
|
||||
|
||||
@@ -30,13 +30,14 @@ from pretix.base.models import (
|
||||
QuestionAnswer, QuestionOption, Quota, Voucher,
|
||||
)
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.base.models.items import ItemAddOn, ItemBundle
|
||||
from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue
|
||||
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, ItemUpdateForm, ItemVariationForm,
|
||||
ItemVariationsFormSet, QuestionForm, QuestionOptionForm, QuotaForm,
|
||||
ItemBundleFormSet, ItemCreateForm, ItemMetaValueForm, ItemUpdateForm,
|
||||
ItemVariationForm, ItemVariationsFormSet, QuestionForm, QuestionOptionForm,
|
||||
QuotaForm,
|
||||
)
|
||||
from pretix.control.permissions import (
|
||||
EventPermissionRequiredMixin, event_permission_required,
|
||||
@@ -939,6 +940,41 @@ class ItemDetailMixin(SingleObjectMixin):
|
||||
raise Http404(_("The requested item does not exist."))
|
||||
|
||||
|
||||
class MetaDataEditorMixin:
|
||||
meta_form = ItemMetaValueForm
|
||||
meta_model = ItemMetaValue
|
||||
|
||||
@cached_property
|
||||
def meta_forms(self):
|
||||
if hasattr(self, 'object') and self.object:
|
||||
val_instances = {
|
||||
v.property_id: v for v in self.object.meta_values.all()
|
||||
}
|
||||
else:
|
||||
val_instances = {}
|
||||
|
||||
formlist = []
|
||||
|
||||
for p in self.request.event.item_meta_properties.all():
|
||||
formlist.append(self._make_meta_form(p, val_instances))
|
||||
return formlist
|
||||
|
||||
def _make_meta_form(self, p, val_instances):
|
||||
return self.meta_form(
|
||||
prefix='prop-{}'.format(p.pk),
|
||||
property=p,
|
||||
instance=val_instances.get(p.pk, self.meta_model(property=p, item=self.object)),
|
||||
data=(self.request.POST if self.request.method == "POST" else None)
|
||||
)
|
||||
|
||||
def save_meta(self):
|
||||
for f in self.meta_forms:
|
||||
if f.cleaned_data.get('value'):
|
||||
f.save()
|
||||
elif f.instance and f.instance.pk:
|
||||
f.instance.delete()
|
||||
|
||||
|
||||
class ItemCreate(EventPermissionRequiredMixin, CreateView):
|
||||
form_class = ItemCreateForm
|
||||
template_name = 'pretixcontrol/item/create.html'
|
||||
@@ -985,7 +1021,7 @@ class ItemCreate(EventPermissionRequiredMixin, CreateView):
|
||||
return super().form_invalid(form)
|
||||
|
||||
|
||||
class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateView):
|
||||
class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataEditorMixin, UpdateView):
|
||||
form_class = ItemUpdateForm
|
||||
template_name = 'pretixcontrol/item/index.html'
|
||||
permission = 'can_change_items'
|
||||
@@ -1038,7 +1074,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.get_object()
|
||||
form = self.get_form()
|
||||
if self.is_valid(form):
|
||||
if self.is_valid(form) and all([f.is_valid() for f in self.meta_forms]):
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
@@ -1088,6 +1124,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
self.save_meta()
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
if form.has_changed() or any(f.has_changed() for f in self.plugin_forms):
|
||||
data = {
|
||||
@@ -1137,6 +1174,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
ctx['plugin_forms'] = self.plugin_forms
|
||||
ctx['meta_forms'] = self.meta_forms
|
||||
ctx['formsets'] = self.formsets
|
||||
|
||||
if not ctx['item'].active and ctx['item'].bundled_with.count() > 0:
|
||||
|
||||
@@ -46,6 +46,7 @@ from pretix.base.models.orders import (
|
||||
from pretix.base.models.tax import EU_COUNTRIES, cc_to_vat_prefix
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.services import tickets
|
||||
from pretix.base.services.cancelevent import cancel_event
|
||||
from pretix.base.services.export import export
|
||||
from pretix.base.services.invoices import (
|
||||
generate_cancellation, generate_invoice, invoice_pdf, invoice_pdf_task,
|
||||
@@ -71,10 +72,11 @@ from pretix.control.forms.filter import (
|
||||
EventOrderFilterForm, OverviewFilterForm, RefundFilterForm,
|
||||
)
|
||||
from pretix.control.forms.orders import (
|
||||
CancelForm, CommentForm, ConfirmPaymentForm, ExporterForm, ExtendForm,
|
||||
MarkPaidForm, OrderContactForm, OrderFeeChangeForm, OrderLocaleForm,
|
||||
OrderMailForm, OrderPositionAddForm, OrderPositionAddFormset,
|
||||
OrderPositionChangeForm, OrderRefundForm, OtherOperationsForm,
|
||||
CancelForm, CommentForm, ConfirmPaymentForm, EventCancelForm, ExporterForm,
|
||||
ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeChangeForm,
|
||||
OrderLocaleForm, OrderMailForm, OrderPositionAddForm,
|
||||
OrderPositionAddFormset, OrderPositionChangeForm, OrderRefundForm,
|
||||
OtherOperationsForm,
|
||||
)
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.views import PaginationMixin
|
||||
@@ -1727,10 +1729,12 @@ class OverView(EventPermissionRequiredMixin, TemplateView):
|
||||
date_filter=self.filter_form.cleaned_data['date_axis'],
|
||||
date_from=self.filter_form.cleaned_data['date_from'],
|
||||
date_until=self.filter_form.cleaned_data['date_until'],
|
||||
fees=True
|
||||
)
|
||||
else:
|
||||
ctx['items_by_category'], ctx['total'] = order_overview(
|
||||
self.request.event,
|
||||
fees=True
|
||||
)
|
||||
ctx['subevent_warning'] = (
|
||||
self.request.event.has_subevents and
|
||||
@@ -1881,3 +1885,66 @@ class RefundList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
def filter_form(self):
|
||||
return RefundFilterForm(data=self.request.GET, event=self.request.event,
|
||||
initial={'status': 'open'})
|
||||
|
||||
|
||||
class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView):
|
||||
template_name = 'pretixcontrol/orders/cancel.html'
|
||||
permission = 'can_change_orders'
|
||||
form_class = EventCancelForm
|
||||
task = cancel_event
|
||||
known_errortypes = ['OrderError']
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'async_id' in request.GET and settings.HAS_CELERY:
|
||||
return self.get_result(request)
|
||||
return FormView.get(self, request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
k = super().get_form_kwargs()
|
||||
k['event'] = self.request.event
|
||||
return k
|
||||
|
||||
def form_valid(self, form):
|
||||
return self.do(
|
||||
self.request.event.pk,
|
||||
subevent=form.cleaned_data['subevent'].pk if form.cleaned_data.get('subevent') else None,
|
||||
auto_refund=form.cleaned_data.get('auto_refund'),
|
||||
keep_fee_fixed=form.cleaned_data.get('keep_fee_fixed'),
|
||||
keep_fee_percentage=form.cleaned_data.get('keep_fee_percentage'),
|
||||
keep_fees=form.cleaned_data.get('keep_fees'),
|
||||
send=form.cleaned_data.get('send'),
|
||||
send_subject=form.cleaned_data.get('send_subject').data,
|
||||
send_message=form.cleaned_data.get('send_message').data,
|
||||
send_waitinglist=form.cleaned_data.get('send'),
|
||||
send_waitinglist_subject=form.cleaned_data.get('send_waitinglist_subject').data,
|
||||
send_waitinglist_message=form.cleaned_data.get('send_waitinglist_message').data,
|
||||
user=self.request.user.pk,
|
||||
)
|
||||
|
||||
def get_success_message(self, value):
|
||||
if value == 0:
|
||||
return _('All orders have been canceled.')
|
||||
else:
|
||||
return _('The orders have been canceled. An error occured with {count} orders, please '
|
||||
'check all uncanceled orders.').format(count=value)
|
||||
|
||||
def get_success_url(self, value):
|
||||
return reverse('control:event.cancel', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
def get_error_url(self):
|
||||
return reverse('control:event.cancel', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
def get_error_message(self, exception):
|
||||
if isinstance(exception, str):
|
||||
return exception
|
||||
return super().get_error_message(exception)
|
||||
|
||||
def form_invalid(self, form):
|
||||
messages.error(self.request, _('Your input was not valid.'))
|
||||
return super().form_invalid(form)
|
||||
|
||||
@@ -278,6 +278,7 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
)
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders'
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
@@ -1009,12 +1010,14 @@ class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
messages.error(request, _('Gift cards are not allowed to have negative values.'))
|
||||
else:
|
||||
self.object.transactions.create(
|
||||
value=value
|
||||
value=value,
|
||||
text=request.POST.get('text') or None,
|
||||
)
|
||||
self.object.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': value
|
||||
'value': value,
|
||||
'text': request.POST.get('text')
|
||||
},
|
||||
user=self.request.user,
|
||||
)
|
||||
|
||||
@@ -540,7 +540,7 @@ class SubEventBulkAction(EventPermissionRequiredMixin, View):
|
||||
)
|
||||
obj.active = True
|
||||
obj.save(update_fields=['active'])
|
||||
messages.success(request, pgettext_lazy('subevent', 'The selected dates have been disabled.'))
|
||||
messages.success(request, pgettext_lazy('subevent', 'The selected dates have been enabled.'))
|
||||
elif request.POST.get('action') == 'delete':
|
||||
return render(request, 'pretixcontrol/subevents/delete_bulk.html', {
|
||||
'allowed': self.objects.filter(orderposition__isnull=True),
|
||||
|
||||
@@ -13,7 +13,8 @@ from django.utils.timezone import make_aware
|
||||
from django.utils.translation import pgettext, ugettext as _
|
||||
|
||||
from pretix.base.models import (
|
||||
EventMetaProperty, EventMetaValue, Order, Organizer, User, Voucher,
|
||||
EventMetaProperty, EventMetaValue, ItemMetaProperty, ItemMetaValue, Order,
|
||||
Organizer, User, Voucher,
|
||||
)
|
||||
from pretix.control.forms.event import EventWizardCopyForm
|
||||
from pretix.control.permissions import event_permission_required
|
||||
@@ -589,3 +590,46 @@ def meta_values(request):
|
||||
for v in sorted(set(defaults.values_list('default', flat=True)[:10]) | set(matches.values_list('value', flat=True)[:10]))
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
def item_meta_values(request, organizer, event):
|
||||
q = request.GET.get('q')
|
||||
propname = request.GET.get('property')
|
||||
|
||||
matches = ItemMetaValue.objects.filter(
|
||||
value__icontains=q,
|
||||
property__name=propname
|
||||
)
|
||||
defaults = ItemMetaProperty.objects.filter(
|
||||
name=propname,
|
||||
default__icontains=q
|
||||
)
|
||||
|
||||
organizer = get_object_or_404(Organizer, slug=organizer)
|
||||
if not request.user.has_organizer_permission(organizer, request=request):
|
||||
raise PermissionDenied()
|
||||
|
||||
defaults = defaults.filter(event__organizer_id=organizer.pk)
|
||||
matches = matches.filter(item__event__organizer_id=organizer.pk)
|
||||
all_access = (
|
||||
request.user.has_active_staff_session(request.session.session_key)
|
||||
or request.user.teams.filter(all_events=True, organizer=organizer, can_change_items=True).exists()
|
||||
)
|
||||
if not all_access:
|
||||
defaults = matches.filter(
|
||||
event__id__in=request.user.teams.filter(can_change_items=True).values_list(
|
||||
'limit_events__id', flat=True
|
||||
)
|
||||
)
|
||||
matches = matches.filter(
|
||||
item__event__id__in=request.user.teams.filter(can_change_items=True).values_list(
|
||||
'limit_events__id', flat=True
|
||||
)
|
||||
)
|
||||
|
||||
return JsonResponse({
|
||||
'results': [
|
||||
{'name': v, 'id': v}
|
||||
for v in sorted(set(defaults.values_list('default', flat=True)[:10]) | set(matches.values_list('value', flat=True)[:10]))
|
||||
]
|
||||
})
|
||||
|
||||
+1565
-1271
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-25 01:00+0000\n"
|
||||
"Last-Translator: Abdullah <abdullah.gumaijan@gmail.com>\n"
|
||||
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -139,44 +139,44 @@ msgstr "يؤدي مسح QR"
|
||||
msgid "Check-in QR"
|
||||
msgstr "تحقق في QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "لا يمكن تحميل ملف PDF الخلفية للأسباب التالية:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "مجموعة من الكائنات"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "كائن النص"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "منطقة الباركود"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "مدعوم من pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "موضوع"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "تصميم تذكرة"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "فشل الادخار."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "خطأ أثناء تحميل ملف PDF الخاصة بك، يرجى المحاولة مرة أخرى."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "هل تريد حقا أن تترك المحرر دون حفظ التغييرات؟"
|
||||
|
||||
@@ -192,37 +192,37 @@ msgstr "توليد رسائل ..."
|
||||
msgid "Unknown error."
|
||||
msgstr "خطأ غير معروف."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "اللون لديه التباين الكبير وهو من السهل جدا أن تقرأ!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr "اللون لديه النقيض لائق وهو على الارجح جيدة بما فيه الكفاية لقراءة!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr "اللون لديه النقيض سيئة للنص على خلفية بيضاء، يرجى اختيار الظل أغمق."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "الكل"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "لا شيء"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "استخدام اسم مختلف داخليا"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "انقر لقريب"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1595
-1323
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -129,44 +129,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -182,37 +182,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1546
-1331
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -129,44 +129,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -182,37 +182,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1548
-1273
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-11-20 14:41+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -142,44 +142,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Baggrunds-pdf'en kunne ikke hentes af følgende grund:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe af objekter"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Tekstobjekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-kode-område"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Drevet af pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Billetdesign"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Gem fejlede."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Fejl under upload af pdf. Prøv venligt igen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Er du sikker på at du vil forlade editoren uden at gemme dine ændringer?"
|
||||
@@ -196,37 +196,37 @@ msgstr "Opretter beskeder …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Ukendt fejl."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1551
-1284
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-06 14:06+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -144,45 +144,45 @@ msgstr "Lead-Scanning-QR-Code"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in-QR-Code"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Event-Ticketshop von pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchten Sie den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
@@ -199,16 +199,16 @@ msgstr "Generiere Nachrichten…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Diese Farbe hat einen sehr guten Kontrast und ist sehr gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und wahrscheinlich gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -216,23 +216,23 @@ msgstr ""
|
||||
"Diese Farbe hat einen schlechten Kontrast für Text auf einem weißen "
|
||||
"Hintergrund. Bitte wählen Sie eine dunklere Farbe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Sie haben ungespeicherte Änderungen!"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-06 14:06+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
@@ -143,45 +143,45 @@ msgstr "Lead-Scanning-QR-Code"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in-QR-Code"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Event-Ticketshop von pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchtest du den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
@@ -198,16 +198,16 @@ msgstr "Generiere Nachrichten…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Diese Farbe hat einen sehr guten Kontrast und ist sehr gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und wahrscheinlich gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -215,23 +215,23 @@ msgstr ""
|
||||
"Diese Farbe hat einen schlechten Kontrast für Text auf einem weißen "
|
||||
"Hintergrund. Bitte wähle eine dunklere Farbe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Du hast ungespeicherte Änderungen!"
|
||||
|
||||
|
||||
+1546
-1331
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -130,44 +130,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -183,37 +183,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1567
-1271
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-10-03 19:00+0000\n"
|
||||
"Last-Translator: Chris Spy <chrispiropoulou@hotmail.com>\n"
|
||||
"Language-Team: Greek <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -148,45 +148,45 @@ msgstr "Οδηγός σάρωσης QR"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Έλεγχος QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"Το αρχείο φόντου PDF δεν ήταν δυνατό να φορτωθεί για τον ακόλουθο λόγο:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Ομάδα αντικειμένων"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Αντικείμενο κειμένου"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Περιοχή Barcode"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Υποστηρίζεται από το Pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Αντικείμενο"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Σχεδιασμός εισιτηρίων"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Η αποθήκευση απέτυχε."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Σφάλμα κατά τη μεταφόρτωση του αρχείου PDF, δοκιμάστε ξανά."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Θέλετε πραγματικά να αφήσετε τον επεξεργαστή χωρίς να αποθηκεύσετε τις "
|
||||
@@ -204,18 +204,18 @@ msgstr "Δημιουργία μηνυμάτων …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Άγνωστο σφάλμα."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει μεγάλη αντίθεση και είναι πολύ εύκολο να το διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει αξιοπρεπή αντίθεση και είναι ίσως αρκετά καλό για να "
|
||||
"διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -223,23 +223,23 @@ msgstr ""
|
||||
"Το χρώμα σας έχει κακή αντίθεση για κείμενο σε λευκό φόντο, επιλέξτε μια πιο "
|
||||
"σκούρα σκιά."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Όλα"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Κανένας"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Χρησιμοποιήστε διαφορετικό όνομα εσωτερικά"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Κάντε κλικ για να κλείσετε"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1568
-1271
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-11-22 10:01+0000\n"
|
||||
"Last-Translator: Carolina Fernández <cfermart@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -145,47 +145,47 @@ msgstr "Escanear QR de clientes potenciales"
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR de Chequeo"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"El fondo del archivo PDF no ha podido ser cargado por la siguiente razón:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Grupo de objetos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Objeto de texto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Área para código de barras"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Proveído por pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objeto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Diseño del ticket"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "El guardado falló."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Ha habido un error mientras se cargaba el archivo PDF, por favor, intente de "
|
||||
"nuevo."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "¿Realmente desea salir del editor sin haber guardado sus cambios?"
|
||||
|
||||
@@ -201,17 +201,17 @@ msgstr "Generando mensajes…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Error desconocido."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "¡Tu color tiene gran contraste y es muy legible!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"¡Tu color tiene un contraste decente y es probablemente suficientemente "
|
||||
"legible!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -219,23 +219,23 @@ msgstr ""
|
||||
"Tu color tiene mal contraste para un texto con fondo blanco, por favor "
|
||||
"escoge un tono más oscuro."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Ninguno"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Usar un nombre diferente internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Click para cerrar"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1591
-1310
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: French\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"PO-Revision-Date: 2019-10-01 01:00+0000\n"
|
||||
"Last-Translator: Fabian Rodriguez <magicfab@legoutdulibre.com>\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2020-02-26 03:00+0000\n"
|
||||
"Last-Translator: David100mark <david.hundertmark@gmx.net>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"fr/>\n"
|
||||
"Language: fr\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 3.5.1\n"
|
||||
"X-Generator: Weblate 3.10.3\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -36,11 +36,11 @@ msgstr "Commandes passées"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Paid orders"
|
||||
msgstr "Ordres payés"
|
||||
msgstr "Commandes payées"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
msgid "Total revenue"
|
||||
msgstr "Revenu total"
|
||||
msgstr "chiffre d'affaires total"
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
|
||||
msgid "Contacting Stripe …"
|
||||
@@ -96,8 +96,6 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:125
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||
#, fuzzy
|
||||
#| msgid "The request took to long. Please try again."
|
||||
msgid "The request took too long. Please try again."
|
||||
msgstr "La requête a prit trop de temps. Veuillez réessayer."
|
||||
|
||||
@@ -144,47 +142,47 @@ msgstr "Balayage du QR code"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Enregistrement QR code"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"Le fichier PDF généré en arrière-plan n'a pas pu être chargé pour la raison "
|
||||
"suivante :"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Groupe d'objets"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Objet texte"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Zone de code-barres"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Généré par pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objet"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Conception des billets"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "L'enregistrement a échoué."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Erreur lors du téléchargement de votre fichier PDF, veuillez réessayer."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Voulez-vous vraiment quitter l'éditeur sans sauvegarder vos modifications ?"
|
||||
@@ -201,17 +199,17 @@ msgstr "Création de messages …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Erreur inconnue."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
"Votre choix de couleur est très facile à lire, il a un excellent contraste !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Votre choix de couleur est assez bon pour la lecture et a un bon contraste !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -219,25 +217,25 @@ msgstr ""
|
||||
"Votre choix de couleur n'a pas un bon contraste avec du texte sur un fond "
|
||||
"blanc, SVP choisissez un ton plus sombre."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Tous"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Aucun"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Utiliser un nom différent en interne"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Cliquez pour fermer"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
msgstr "Vous avez des modifications non sauvegardées !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/orderchange.js:24
|
||||
msgid "Calculating default price…"
|
||||
|
||||
+1551
-1331
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2020-01-24 08:00+0000\n"
|
||||
"Last-Translator: Prokaj Miklós <mixolid0@gmail.com>\n"
|
||||
"Language-Team: Hungarian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -142,44 +142,44 @@ msgstr "QR Scan"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check in QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "A PDF háttér fájl nem tölthető be a következők miatt:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "tárgy csoport"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Szöveg"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Vonalkód terület"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "pretix által működtetett"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "objektum"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Jegy design"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Mentés sikertelen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Hiba a PDF fájl feltöltése közben, próbálja újra."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Biztosan ki akar lépni a szerkesztőből a változtatások mentése nélkül?"
|
||||
|
||||
@@ -195,16 +195,16 @@ msgstr "Üzenetek generálása…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Ismeretlen hiba."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "A választott színek remek kontrasztot adnak, és nagyon könnyű olvasni!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"A választott színek kontrasztja elégséges, és valószínűleg jól olvasható!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -212,23 +212,23 @@ msgstr ""
|
||||
"A választott színek kontrasztja elégtelen, kérjük válassz sötétebb "
|
||||
"árnyalatot."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Összes"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Semmi"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Használj másik nevet"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Bezárásért kattints"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Mentetlen változtatások!"
|
||||
|
||||
|
||||
+1563
-1336
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-20 19:00+0000\n"
|
||||
"Last-Translator: Patrick Arminio <patrick.arminio@gmail.com>\n"
|
||||
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -146,44 +146,44 @@ msgstr "Scansiona QR del lead"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in con QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Il file PDF di sfondo non può essere caricato per le seguenti ragioni:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppo di oggetti"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Oggetto testo"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Area codice a barra"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Realizzato con pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Oggetto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Design biglietto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Salvataggio fallito."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Errore durante il caricamento del tuo file PDF, prova di nuovo."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Vuoi davvero abbandonare l'editor senza salvare le modifiche?"
|
||||
|
||||
@@ -199,39 +199,39 @@ msgstr "Stiamo generando i messaggi …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Errore sconosciuto."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Il colore scelto ha un ottimo contrasto ed è molto leggibile!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Il colore scelto ha un buon contrasto e probabilmente è abbastanza leggibile!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
"Il colore scelto non ha un buon contrasto, per favore scegline uno più scuro."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Tutto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Nessuno"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Utilizza un nome diverso internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Clicca per chiudere"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Hai cambiamenti non salvati!"
|
||||
|
||||
|
||||
+1569
-1325
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-11-13 06:00+0000\n"
|
||||
"Last-Translator: Zane Smite <z.smite@riga-jurmala.com>\n"
|
||||
"Language-Team: Latvian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -146,45 +146,45 @@ msgstr "Galvenās skenēšanas QR"
|
||||
msgid "Check-in QR"
|
||||
msgstr "Reģistrācijas QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Fona PDF fails nevarēja ielādēties sekojoša iemesla dēļ:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Objektu grupa"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Teksta objekts"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Svītru koda lauks"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Pretix atbalstīts"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objekts"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Biļešu dizains"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Saglabāšana neizdevās."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Radusies kļūda augšupielādējot jūsu PDF failu, lūdzu, mēģiniet vēlreiz."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Vai jūs tiešām vēlaties iziet no rediģēšanas lauka bez veikto izmaiņu "
|
||||
@@ -202,17 +202,17 @@ msgstr "Ziņas tiek ģenerētas …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Nezināma kļūda."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Izvēlētā teksta krāsa ļoti labi izceļas un ir viegli lasāma!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Izvēlētā teksta krāsa pietiekami izceļas un visdrīzāk būs samērā viegli "
|
||||
"lasāma!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -220,23 +220,23 @@ msgstr ""
|
||||
"Izvēlētā krāsa tekstam neizceļas uz esošā fona, lūdzu, izvēlieties tumšāku "
|
||||
"krāsu."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Visi"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Neviens"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Izmantojiet citu nosaukumu iekšēji"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Noklikšķiniet, lai aizvērtu"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -130,44 +130,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -183,37 +183,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+1738
-1542
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-07 06:00+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -141,44 +141,44 @@ msgstr "QR-code voor lead-scanning"
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR-code voor check-in"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Het PDF-achtergrondbestand kon niet geladen worden met als reden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Groep van objecten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Tekstobject"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Barcode gebied"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Mogelijk gemaakt door pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Object"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticketontwerp"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Opslaan mislukt."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Probleem bij het uploaden van het PDF-bestand, probeer het opnieuw."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Wilt u de editor verlaten zonder uw wijzigingen op te slaan?"
|
||||
|
||||
@@ -194,16 +194,16 @@ msgstr "Bezig met het genereren van berichten …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Onbekende fout."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Uw kleur heeft een goed contrast, en is gemakkelijk te lezen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Uw kleur heeft een redelijk contrast, en is waarschijnlijk goed te lezen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -211,23 +211,23 @@ msgstr ""
|
||||
"Uw kleur heeft een slecht contrast voor tekst op een witte achtergrond, kies "
|
||||
"een donkerdere kleur."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Geen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Gebruik intern een andere naam"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Klik om te sluiten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "U heeft nog niet opgeslagen wijzigingen!"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -129,44 +129,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -182,37 +182,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-12-16 04:00+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
|
||||
@@ -142,45 +142,45 @@ msgstr "QR-code voor lead-scanning"
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR-code voor check-in"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"Het PDF-achtergrondbestand kon niet geladen worden om de volgende reden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Groep van objecten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Tekstobject"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Barcodegebied"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Mogelijk gemaakt door pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Object"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Kaartjesontwerp"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Opslaan mislukt."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Probleem bij het uploaden van het PDF-bestand, probeer het opnieuw."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Wil je de editor verlaten zonder je wijzigingen op te slaan?"
|
||||
|
||||
@@ -196,16 +196,16 @@ msgstr "Bezig met het genereren van berichten …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Onbekende fout."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Je kleur heeft een goed contrast, en is gemakkelijk te lezen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Je kleur heeft een redelijk contrast, en is waarschijnlijk goed te lezen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -213,23 +213,23 @@ msgstr ""
|
||||
"Je kleur heeft een slecht contrast voor tekst op een witte achtergrond, kies "
|
||||
"een donkerdere kleur."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Geen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Gebruik intern een andere naam"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Klik om te sluiten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Je hebt nog niet opgeslagen wijzigingen!"
|
||||
|
||||
|
||||
+1567
-1326
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-09-24 19:00+0000\n"
|
||||
"Last-Translator: Serge Bazanski <q3k@hackerspace.pl>\n"
|
||||
"Language-Team: Polish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -146,44 +146,44 @@ msgstr "QR kod pozyskania lead'u"
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR zameldowania"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Błąd ładowania pliku PDF tła:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Grupa obiektów"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Obiekt tekstowy"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Miejsce na kod kreskowy"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Wygenerowane przez pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Obiekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Projekt biletu"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Błąd zapisu."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Błąd uploadu pliku PDF, prosimy spróbować ponownie."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Czy na pewno opuścić edytor bez zapisania zmian?"
|
||||
|
||||
@@ -199,16 +199,16 @@ msgstr "Generowanie wiadomości…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Nieznany błąd."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Wybrany kolor ma wysoki kontrast i zapewnia doskonałą czytelność!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Wybrany kolor ma odpowiedni kontrast i zapewnia wystarczającą czytelność!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -216,23 +216,23 @@ msgstr ""
|
||||
"Wybrany kolor ma za słaby kontrast dla tekstu na białym tle, prosimy wybrać "
|
||||
"ciemniejszy odcień."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Zaznacz wszystko"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Odznacz wszystko"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Użyj innej nazwy wewnętrznie"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Zamknij"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -130,44 +130,44 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -183,37 +183,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-02-17 15:22+0000\n"
|
||||
"POT-Creation-Date: 2020-03-03 15:55+0000\n"
|
||||
"PO-Revision-Date: 2019-03-19 09:00+0000\n"
|
||||
"Last-Translator: Vitor Reis <vitor.reis7@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://translate.pretix.eu/projects/"
|
||||
@@ -152,44 +152,44 @@ msgstr "Ler QR"
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR Check-in"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:267
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:269
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "O arquivo de fundo PDF não pôde ser carregado pelo seguinte motivo:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:450
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:452
|
||||
msgid "Group of objects"
|
||||
msgstr "Grupo de objetos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:456
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
msgid "Text object"
|
||||
msgstr "Objeto de texto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:458
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
msgid "Barcode area"
|
||||
msgstr "Área de código de barras"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:460
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Distribuído por pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:462
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:464
|
||||
msgid "Object"
|
||||
msgstr "Objeto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:468
|
||||
msgid "Ticket design"
|
||||
msgstr "Design de bilhetes"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:723
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:725
|
||||
msgid "Saving failed."
|
||||
msgstr "Erro ao salvar."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:772
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:810
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:774
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:812
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Erro durante o upload do seu arquivo PDF, tente novamente."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:795
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:797
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Você realmente quer deixar o editor sem salvar suas mudanças?"
|
||||
|
||||
@@ -205,17 +205,17 @@ msgstr "Gerando mensagens …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Erro desconhecido."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:231
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:232
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Sua cor tem grande contraste e é muito fácil de ler!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:235
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:236
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Sua cor tem um contraste aceitável e provavelmente é boa o suficiente para "
|
||||
"ler!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:239
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:240
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -223,23 +223,23 @@ msgstr ""
|
||||
"Sua cor tem um contraste ruim para o texto sobre fundo branco, por favor, "
|
||||
"escolha um tom mais escuro."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:355
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:357
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:356
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:358
|
||||
msgid "None"
|
||||
msgstr "Nenhum"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:677
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:679
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Use um nome diferente internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:734
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:736
|
||||
msgid "Click to close"
|
||||
msgstr "Clique para fechar"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:749
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:751
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user