Compare commits

...

78 Commits

Author SHA1 Message Date
Raphael Michel f78e54f2a1 Fix #575 -- Do not extend card expiry on failed card operations 2020-03-09 21:21:28 +01:00
Raphael Michel 23a52eb12a Add lang attribute to <html> tag in presale 2020-03-08 15:23:47 +01:00
Raphael Michel 79ecb231f2 Fix placement of back link when a header is used 2020-03-08 15:07:59 +01:00
Raphael Michel 08de7f59a3 Move iframe.js into main JS file 2020-03-08 15:07:59 +01:00
Raphael Michel 0de3c33bab Remove unused bootstrap components from CSS 2020-03-08 15:07:59 +01:00
Raphael Michel a4ae8b0e66 Include lightbox in main.scss file 2020-03-08 15:07:59 +01:00
Raphael Michel be1bf81298 Add font-display: swap to custom shop fonts 2020-03-08 15:07:59 +01:00
Raphael Michel b7528ae1cf Cancelling events: Fix incorrect refund amount in emails 2020-03-06 18:09:38 +01:00
Raphael Michel 4f6712ccbe OrderChangeManager: Prevent creation of 0 € invoices 2020-03-06 17:05:15 +01:00
Raphael Michel 939335f94b Widget: Fix incorrect computation of cache key 2020-03-06 17:00:47 +01:00
Raphael Michel c849276a35 Widget: Allow to filter by product 2020-03-06 17:00:26 +01:00
Raphael Michel 8e9f0f07a1 Optimize performance of waiting list dashboard tile 2020-03-06 14:03:28 +01:00
Raphael Michel 389884d191 shell_scoped: Fall back to shell if shell_plus is not installed 2020-03-06 14:03:06 +01:00
Raphael Michel d8c2c82da7 Update invoice language in build_invoice 2020-03-06 09:36:20 +01:00
Raphael Michel c3ed3d4899 Adjust tests for last commit 2020-03-05 18:12:40 +01:00
Raphael Michel e9235cd433 Bank transfer: ignore order status when manually assigning amount 2020-03-05 17:37:54 +01:00
Raphael Michel 975b6d800a Fix hardcoded PK in test 2020-03-05 17:09:33 +01:00
Raphael Michel ee260c8231 API: Allow to simulate orders 2020-03-05 16:37:55 +01:00
Raphael Michel f7fddc05dd Improve caching of widget.js 2020-03-05 13:09:42 +01:00
Raphael Michel eaa61c7795 Add @gzip_page to widget views 2020-03-05 12:53:17 +01:00
Raphael Michel d4994258e6 Avoid issues with duplicate ItemBundles 2020-03-05 12:53:02 +01:00
Raphael Michel 9b50ec2d74 Cancelling events: Allow to inform waiting list 2020-03-05 10:22:59 +01:00
Raphael Michel 447b6b7fee Waiting list: Do not send notifications for disabled items 2020-03-05 09:37:35 +01:00
Raphael Michel 40f763c999 Cancelling events: Create special log entry 2020-03-05 09:37:17 +01:00
Raphael Michel 6a3d05be9e Cancelling events: Fix invalid email logging 2020-03-05 09:23:07 +01:00
Raphael Michel 766447f021 Fix typo in form field name 2020-03-04 14:45:54 +01:00
Raphael Michel 5fbeb90f00 Order import: Fix crash on unknown delimiter
PRETIXEU-1Y0
2020-03-04 14:44:55 +01:00
Raphael Michel c01cc85eda Merge pull request #1597 from pretix-translations/weblate-pretix-pretix
Translations update from Weblate
2020-03-03 17:13:10 +01:00
Raphael Michel 4a054da6ee Translated on translate.pretix.eu (German (informal))
Currently translated at 100.0% (3510 of 3510 strings)

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

powered by weblate
2020-03-03 17:11:12 +01:00
Raphael Michel 583a2b6572 Translated on translate.pretix.eu (German)
Currently translated at 100.0% (3510 of 3510 strings)

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

powered by weblate
2020-03-03 17:11:11 +01:00
Raphael Michel fbe025afb2 Translated on translate.pretix.eu (German (informal))
Currently translated at 100.0% (3488 of 3488 strings)

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

powered by weblate
2020-03-03 16:56:06 +01:00
Raphael Michel 66e6191122 Translated on translate.pretix.eu (German)
Currently translated at 100.0% (3488 of 3488 strings)

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

powered by weblate
2020-03-03 16:56:05 +01:00
Raphael Michel 0f26f0787c Update po files
[CI skip]

Signed-off-by: Raphael Michel <mail@raphaelmichel.de>
2020-03-03 16:55:56 +01:00
Raphael Michel 62a86c9b4a Allow to cancel all orders in an event (#1596)
* Allow to cancel all orders in an event

* Add tests

* Actually add tests
2020-03-03 16:55:05 +01:00
Raphael Michel 07318be4c9 Fix incorrect total in invoice preview 2020-03-03 16:45:18 +01:00
Raphael Michel 3c8ef2c620 Fix incorrect result message 2020-03-03 16:43:36 +01:00
Raphael Michel a858f47220 API: Fix crash when cancelling a redeemed gift card 2020-03-02 13:18:16 +01:00
Raphael Michel 381fa5e1cd Allow to add a text to gift card transactions 2020-03-02 12:47:39 +01:00
Raphael Michel 1539eea664 API: Allow devices to access gift cards 2020-03-02 12:19:19 +01:00
Raphael Michel 3d41d1331a API: Support for cross-organizer gift cards 2020-03-02 12:19:02 +01:00
Raphael Michel 00848b3339 Remove "default" flag from cloned layouts 2020-03-02 09:35:53 +01:00
Raphael Michel d174b11c6a Reduce retention time of sass compiler cache 2020-02-28 16:21:34 +01:00
Raphael Michel a501ce496a Fix broken sass compiler cache 2020-02-28 16:21:18 +01:00
Raphael Michel de277cc959 Badges, PDF tickets: Allow to copy layouts 2020-02-28 12:50:31 +01:00
Raphael Michel 12b3ae81d6 Mark payment_term_days settings as required in the backend 2020-02-28 12:24:00 +01:00
Raphael Michel fcdb40dda0 Refs #1593 -- Fix subsequent issue when clearing the cart 2020-02-27 16:28:07 +01:00
Raphael Michel f65cf8e86a Fix checks for min_per_order and max_per_order in combination with variations 2020-02-27 15:08:35 +01:00
Raphael Michel 12540238b7 Ignore replica database in tests 2020-02-27 14:44:20 +01:00
Raphael Michel 398a30e33a Merge pull request #1592 from pretix-translations/weblate-pretix-pretix
Translations update from Weblate
2020-02-27 11:05:27 +01:00
Raphael Michel 3410640618 Translated on translate.pretix.eu (German (informal))
Currently translated at 100.0% (3488 of 3488 strings)

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

powered by weblate
2020-02-27 11:05:05 +01:00
Raphael Michel 7b45cfccc2 Translated on translate.pretix.eu (German)
Currently translated at 100.0% (3488 of 3488 strings)

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

powered by weblate
2020-02-27 11:05:04 +01:00
Raphael Michel 33f503aea1 Update po files
[CI skip]

Signed-off-by: Raphael Michel <mail@raphaelmichel.de>
2020-02-27 10:55:11 +01:00
Raphael Michel 3fd650081b Allowing more options to style pretix shops (#1585)
* Fix caching issues in SASS compilation

* Allow to set a custom page background color

* Allow to disable round corners

* Support larger header pictures

* Allow to show title despite header

* Move language picker

* FIx widget styles
2020-02-27 10:54:00 +01:00
Martin Gross b622854be6 Fix versionchanged for item_meta_data 2020-02-27 09:25:44 +01:00
Raphael Michel 6d00daa9ee Fix crash when sending mails with empty mail_from 2020-02-26 17:34:37 +01:00
Raphael Michel f27148998a Support for itemmeta: objects in the API 2020-02-26 15:59:42 +01:00
Raphael Michel 4a0369cc37 REbase migration 2020-02-26 15:22:41 +01:00
Martin Gross 76aaf61e19 Add meta_data for items (#1576)
* PoC for ItemMetaProperties/Values

* Missing is_valid

* ItemMetaProperties/Values in editable via API, cloneable

* Tests

* Add Docs

* Fix import order

* Fix another import sorting...

* Typeahead for ItemMetaValues

* Test for editing event-objects

* Fix typeahead permission checks

* Further access restriction

Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
2020-02-26 15:06:24 +01:00
Raphael Michel dd1e5fa929 Test suite: Allow to cancel expired orders 2020-02-26 11:56:23 +01:00
Raphael Michel 4a2516e303 Allow to cancel expired orders 2020-02-26 11:23:52 +01:00
Raphael Michel cf06712eca Merge pull request #1590 from pretix-translations/weblate-pretix-pretix
Translations update from Weblate
2020-02-26 08:51:30 +01:00
Maarten van den Berg 6185d675f0 Translated on translate.pretix.eu (Dutch (informal))
Currently translated at 97.5% (3388 of 3474 strings)

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

powered by weblate
2020-02-26 04:00:13 +01:00
David100mark a53cd3abce Translated on translate.pretix.eu (French)
Currently translated at 100.0% (103 of 103 strings)

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

powered by weblate
2020-02-26 04:00:12 +01:00
David100mark ebe86a17fb Translated on translate.pretix.eu (French)
Currently translated at 66.9% (2325 of 3474 strings)

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

powered by weblate
2020-02-26 04:00:11 +01:00
David100mark d189b16ee7 Translated on translate.pretix.eu (German)
Currently translated at 100.0% (3474 of 3474 strings)

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

powered by weblate
2020-02-26 04:00:11 +01:00
Raphael Michel d70ce4491a Merge pull request #1584 from pretix-translations/weblate-pretix-pretix
Translations update from Weblate
2020-02-20 16:12:22 +01:00
Maarten van den Berg 607ff48d70 Translated on translate.pretix.eu (Dutch (informal))
Currently translated at 97.4% (3382 of 3474 strings)

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

powered by weblate
2020-02-19 18:25:18 +01:00
Maarten van den Berg 4bab44ca85 Translated on translate.pretix.eu (Dutch)
Currently translated at 100.0% (3474 of 3474 strings)

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

powered by weblate
2020-02-19 18:25:18 +01:00
Raphael Michel a5cdb485d0 Fix faulty test cases 2020-02-19 18:25:05 +01:00
Raphael Michel 282ef792c4 Do not show "create new event" if there are no permissions to dos o 2020-02-19 18:24:47 +01:00
Raphael Michel 6cd888a1dc Fix date parsing issue in Danish locale 2020-02-19 18:00:02 +01:00
Raphael Michel 2e5b80c83c Fix missing fees in order overview 2020-02-19 16:09:40 +01:00
Raphael Michel 4511110069 Fix timezone of notifications 2020-02-19 14:28:06 +01:00
Raphael Michel 1af1d8c658 Add rich_text_snippet 2020-02-18 09:45:20 +01:00
Raphael Michel 9f6a3f9a6a Add custom field for invoice addresses 2020-02-18 09:21:00 +01:00
Raphael Michel 1c03d5d305 Invoices: Label tax ID as ABN in Australia 2020-02-18 09:05:09 +01:00
Raphael Michel 69a1fccd20 Fix #1582 - Add explicit requirement to packaging library 2020-02-17 21:00:44 +01:00
Raphael Michel 2a54aa2d83 Bump to 3.7.0.dev0 2020-02-17 16:39:27 +01:00
161 changed files with 44477 additions and 35245 deletions
+12
View File
@@ -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",
+5
View File
@@ -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
+10
View File
@@ -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,
+7
View File
@@ -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
+11
View File
@@ -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
View File
@@ -1 +1 @@
__version__ = "3.6.0"
__version__ = "3.7.0.dev0"
+53 -1
View File
@@ -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',
+53 -3
View File
@@ -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
+96 -22
View File
@@ -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'
+11 -5
View File
@@ -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
+26 -3
View File
@@ -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)
+9
View File
@@ -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),
+6 -1
View File
@@ -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', '')
+6
View File
@@ -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),
),
]
+3 -3
View File
@@ -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
+1
View File
@@ -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:
+15 -1
View File
@@ -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]
+1
View File
@@ -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",)
+8 -1
View File
@@ -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()])
+66 -1
View File
@@ -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)
+8 -6
View File
@@ -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.'),
+2
View File
@@ -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:
+223
View File
@@ -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
+32 -46
View File
@@ -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)
+7 -8
View File
@@ -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,
+1 -1
View File
@@ -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))
+2 -1
View File
@@ -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":
+5 -1
View File
@@ -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
+76 -50
View File
@@ -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()
+2
View File
@@ -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
+42 -2
View File
@@ -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')
+25 -6
View File
@@ -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)
+38 -3
View File
@@ -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()
}
+47 -1
View File
@@ -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()
}
+153 -12
View File
@@ -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)
+23 -2
View File
@@ -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'),
+6
View File
@@ -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"
+3
View File
@@ -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'),
+42 -15
View File
@@ -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(
+42 -4
View File
@@ -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={
+43 -5
View File
@@ -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:
+71 -4
View File
@@ -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)
+5 -2
View File
@@ -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,
)
+1 -1
View File
@@ -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),
+45 -1
View File
@@ -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]))
]
})
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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
+20 -20
View File
@@ -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
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+26 -28
View File
@@ -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…"
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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!"
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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!"
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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
+20 -20
View File
@@ -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 ""
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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
+20 -20
View File
@@ -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!"
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -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
+20 -20
View File
@@ -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