Compare commits

..

43 Commits

Author SHA1 Message Date
Raphael Michel
ee70104735 Bump version to 2.5.0 2019-03-11 18:12:29 +01:00
Raphael Michel
8ba38a0254 Order.meta_info_data: Expose null values as an empty dict 2019-03-11 18:12:29 +01:00
Raphael Michel
761a03abdc Merge pull request #1200 from pretix-translations/weblate-pretix-pretix
Update from Weblate
2019-03-11 16:42:02 +01:00
Raphael Michel
f3b63acd40 Translated on translate.pretix.eu (German)
Currently translated at 100.0% (3010 of 3010 strings)

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

powered by weblate
2019-03-11 15:41:46 +00:00
Raphael Michel
9eee967050 Translated on translate.pretix.eu (German (informal))
Currently translated at 100.0% (3010 of 3010 strings)

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

powered by weblate
2019-03-11 15:41:24 +00:00
Raphael Michel
02aee0637a Update po files
[CI skip]

Signed-off-by: Raphael Michel <mail@raphaelmichel.de>
2019-03-11 16:02:41 +01:00
Raphael Michel
dde99c45f3 Merge pull request #1194 from pretix-translations/weblate-pretix-pretix
Update from Weblate
2019-03-11 16:02:01 +01:00
徐志能
74292535ad Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 21.2% (635 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
徐志能
d1e3ba778d Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 10.7% (320 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
yichengsd
475835959d Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 10.7% (320 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
yichengsd
efdeaeac83 Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 100.0% (68 of 68 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
yichengsd
56fe37dd67 Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 6.2% (186 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
yichengsd
ca07f48afd Translated on translate.pretix.eu (Chinese (Simplified))
Currently translated at 6.2% (185 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Raphael Michel
fa706549ce Added translation on translate.pretix.eu (Chinese (Simplified)) 2019-03-11 13:36:08 +00:00
Raphael Michel
989b28c2f6 Added translation on translate.pretix.eu (Chinese (Simplified)) 2019-03-11 13:36:08 +00:00
Raphael Michel
1c84660c42 Translated on translate.pretix.eu (German (informal))
Currently translated at 100.0% (3000 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Alvaro Enrique Ruano
cf58447cd4 Translated on translate.pretix.eu (Spanish)
Currently translated at 100.0% (3000 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
arabestia
305a3aaf9f Translated on translate.pretix.eu (Spanish)
Currently translated at 100.0% (3000 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Alvaro Enrique Ruano
b54a8c120f Translated on translate.pretix.eu (Spanish)
Currently translated at 96.1% (2884 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Maarten van den Berg
89684c8e0f Translated on translate.pretix.eu (Dutch (informal))
Currently translated at 100.0% (3000 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Maarten van den Berg
c5566dfee7 Translated on translate.pretix.eu (Dutch)
Currently translated at 100.0% (3000 of 3000 strings)

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

powered by weblate
2019-03-11 13:36:08 +00:00
Raphael Michel
5e7ee3c047 Delete cart positions if deleting subevent
Fixes sentry issue PRETIXEU-Y4
2019-03-11 14:35:49 +01:00
Raphael Michel
815ee29a50 Sendmail: Backwards compatbility of from_log
Fixes sentry issue PRETIXEU-Y3
2019-03-11 14:34:41 +01:00
Raphael Michel
13ee691133 Banktransfer: CSV import of Mac CSV files 2019-03-11 14:30:43 +01:00
Raphael Michel
4e3dd24209 Order list: Prevent type error on empty result set 2019-03-08 13:53:18 +01:00
Raphael Michel
7ef4adeb73 Adjust to new isort version 2019-03-08 12:50:35 +01:00
Raphael Michel
7be5331da5 Show ticket code in check-in list 2019-03-08 12:50:25 +01:00
Raphael Michel
12fc02b2e4 Pagination: Remove hover effect of current page indicator 2019-03-08 12:30:13 +01:00
Raphael Michel
86b4835273 Go to order: Allow to pass an invoice number 2019-03-08 12:22:19 +01:00
Raphael Michel
e53818b025 Sendmail history: Show selected items 2019-03-08 12:18:13 +01:00
Raphael Michel
206a0a28c7 Render markdown in all e-mail previews 2019-03-08 12:15:06 +01:00
Raphael Michel
461b0b639c Sendmail: Use multi-select for product selection 2019-03-08 12:14:40 +01:00
Raphael Michel
2e6f5d0f32 E-Mail rendering: Consistent markdown evaluation between preview and mail 2019-03-08 11:58:26 +01:00
Raphael Michel
12b48948e3 Add a new notification category for overpayments 2019-03-08 11:40:22 +01:00
Raphael Michel
87c7a3d26f PayPal: Even a canceled payment can still succeed 2019-03-08 11:33:03 +01:00
Raphael Michel
4c0789ac20 Fix inconsistent naming of option 2019-03-08 11:30:04 +01:00
Raphael Michel
bc4e6fa549 Add new API endpoints to documentation 2019-03-06 09:39:58 +01:00
Raphael Michel
2b8949dea4 Add API for badge and ticket layout assignments 2019-03-06 09:35:08 +01:00
Raphael Michel
f3ef00e3b7 Set an update_check_id even if update checks are disabled 2019-03-06 09:09:18 +01:00
Martin Gross
c5499df0b4 Improve display of date/time-format in PDF-ticket preview vs. actual rendering (Z#2344558) 2019-03-05 12:10:05 +01:00
Raphael Michel
68dbfedfdf Add database-level uniqueness constraint for check-ins
We measured that this creates a ~10% performance loss on MySQL, but
believe that correctness is more important. Also, in case on concurrent
check-ins on MySQL with default transaction isolation level, this might
lead to Internal Server Errors on all but one check-ins, which is still
better than to show green.
2019-03-04 18:51:52 +01:00
Raphael Michel
e70738ae0c Fix percentage bar in list of check-in lists 2019-03-04 18:44:21 +01:00
Raphael Michel
5750201bc3 Position API: search in attendee_email 2019-03-04 11:04:39 +01:00
76 changed files with 25868 additions and 9166 deletions

View File

@@ -108,3 +108,43 @@ Endpoints
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/badgeitems/
Returns a list of all assignments of items to layouts
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/democon/badgeitems/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"layout": 2,
"item": 3,
}
]
}
:query page: The page number in case of a multi-page result set, default is 1
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.

View File

@@ -114,3 +114,44 @@ Endpoints
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/ticketlayoutitems/
Returns a list of all assignments of items to layouts
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/democon/ticketlayoutitems/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"layout": 2,
"item": 3,
"sales_channel": web
}
]
}
:query page: The page number in case of a multi-page result set, default is 1
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of a valid event
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.

View File

@@ -1 +1 @@
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"

View File

@@ -397,6 +397,8 @@ class OrderPositionFilter(FilterSet):
Q(secret__istartswith=value)
| Q(attendee_name_cached__icontains=value)
| Q(addon_to__attendee_name_cached__icontains=value)
| Q(attendee_email__icontains=value)
| Q(addon_to__attendee_email__icontains=value)
| Q(order__code__istartswith=value)
| Q(order__invoice_address__name_cached__icontains=value)
| Q(order__email__icontains=value)

View File

@@ -1,8 +1,6 @@
import logging
from smtplib import SMTPResponseException
import bleach
import markdown
from django.conf import settings
from django.core.mail.backends.smtp import EmailBackend
from django.dispatch import receiver
@@ -12,7 +10,7 @@ from inlinestyler.utils import inline_css
from pretix.base.models import Event, Order
from pretix.base.signals import register_html_mail_renderers
from pretix.base.templatetags.rich_text import markdown_compile
from pretix.base.templatetags.rich_text import markdown_compile_email
logger = logging.getLogger('pretix.base.email')
@@ -98,7 +96,7 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
raise NotImplementedError()
def render(self, plain_body: str, plain_signature: str, subject: str, order: Order) -> str:
body_md = bleach.linkify(markdown_compile(plain_body))
body_md = markdown_compile_email(plain_body)
htmlctx = {
'site': settings.PRETIX_INSTANCE_NAME,
'site_url': settings.SITE_URL,
@@ -112,7 +110,7 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
if plain_signature:
signature_md = plain_signature.replace('\n', '<br>\n')
signature_md = bleach.linkify(bleach.clean(markdown.markdown(signature_md), tags=bleach.ALLOWED_TAGS + ['p', 'br']))
signature_md = markdown_compile_email(signature_md)
htmlctx['signature'] = signature_md
if order:

View File

@@ -92,7 +92,7 @@ class ListExporter(BaseExporter):
choices=(
('xlsx', _('Excel (.xlsx)')),
('default', _('CSV (with commas)')),
('excel', _('CSV (Excel-style)')),
('csv-excel', _('CSV (Excel-style)')),
('semicolon', _('CSV (with semicolons)')),
),
)),

View File

@@ -0,0 +1,27 @@
# Generated by Django 2.1.5 on 2019-03-04 17:26
from django.db import migrations
from django.db.models import Count
def make_checkins_unique(apps, se):
Checkin = apps.get_model('pretixbase', 'Checkin')
for d in Checkin.objects.order_by().values('list_id', 'position_id').annotate(c=Count('id')).filter(c__gt=1):
for c in Checkin.objects.filter(list_id=d['list_id'], position_id=d['position_id'])[:d['c'] - 1]:
c.delete()
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0111_auto_20190219_0949'),
]
operations = [
migrations.RunPython(
make_checkins_unique, migrations.RunPython.noop,
),
migrations.AlterUniqueTogether(
name='checkin',
unique_together={('list', 'position')},
),
]

View File

@@ -167,6 +167,9 @@ class Checkin(models.Model):
'pretixbase.CheckinList', related_name='checkins', on_delete=models.PROTECT,
)
class Meta:
unique_together = (('list', 'position'),)
def __repr__(self):
return "<Checkin: pos {} on list '{}' at {}>".format(
self.position, self.list, self.datetime

View File

@@ -229,6 +229,8 @@ class Order(LockModel, LoggedModel):
@cached_property
def meta_info_data(self):
if not self.meta_info:
return {}
try:
return json.loads(self.meta_info)
except TypeError:
@@ -1086,7 +1088,7 @@ class OrderPayment(models.Model):
"""
return self.order.event.get_payment_providers().get(self.provider)
def _mark_paid(self, force, count_waitinglist, user, auth):
def _mark_paid(self, force, count_waitinglist, user, auth, overpaid=False):
from pretix.base.signals import order_paid
can_be_paid = self.order._can_be_paid(count_waitinglist=count_waitinglist)
if not force and can_be_paid is not True:
@@ -1103,6 +1105,9 @@ class OrderPayment(models.Model):
'date': self.payment_date,
'force': force
}, user=user, auth=auth)
if overpaid:
self.order.log_action('pretix.event.order.overpaid', {}, user=user, auth=auth)
order_paid.send(self.order.event, order=self.order)
def confirm(self, count_waitinglist=True, send_mail=True, force=False, user=None, auth=None, mail_text=''):
@@ -1168,10 +1173,10 @@ class OrderPayment(models.Model):
# Performance optimization. In this case, there's really no reason to lock everything and an atomic
# database transaction is more than enough.
with transaction.atomic():
self._mark_paid(force, count_waitinglist, user, auth)
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total)
else:
with self.order.event.lock():
self._mark_paid(force, count_waitinglist, user, auth)
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total)
invoice = None
if invoice_qualified(self.order):

View File

@@ -236,6 +236,12 @@ def register_default_notification_types(sender, **kwargs):
_('Order changed'),
_('Order {order.code} has been changed.')
),
ParametrizedOrderNotificationType(
sender,
'pretix.event.order.overpaid',
_('Order has been overpaid'),
_('Order {order.code} has been overpaid.')
),
ParametrizedOrderNotificationType(
sender,
'pretix.event.order.refund.created.externally',

View File

@@ -110,7 +110,18 @@ DEFAULT_VARIABLES = OrderedDict((
("event_begin", {
"label": _("Event begin date and time"),
"editor_sample": _("2017-05-31 20:00"),
"evaluate": lambda op, order, ev: ev.get_date_from_display(show_times=True)
"evaluate": lambda op, order, ev: date_format(
ev.date_from.astimezone(timezone(ev.settings.timezone)),
"SHORT_DATETIME_FORMAT"
) if ev.date_from else ""
}),
("event_begin_date", {
"label": _("Event begin date"),
"editor_sample": _("2017-05-31"),
"evaluate": lambda op, order, ev: date_format(
ev.date_from.astimezone(timezone(ev.settings.timezone)),
"SHORT_DATE_FORMAT"
) if ev.date_from else ""
}),
("event_begin_time", {
"label": _("Event begin time"),

View File

@@ -670,15 +670,15 @@ class CartManager:
self._check_max_cart_size()
self._calculate_expiry()
# with self.event.lock() as now_dt:
with transaction.atomic():
self.now_dt = now()
self._extend_expiry_of_valid_existing_positions()
err = self._delete_out_of_timeframe()
err = self.extend_expired_positions() or err
err = self._perform_operations() or err
if err:
raise CartError(err)
with self.event.lock() as now_dt:
with transaction.atomic():
self.now_dt = now_dt
self._extend_expiry_of_valid_existing_positions()
err = self._delete_out_of_timeframe()
err = self.extend_expired_positions() or err
err = self._perform_operations() or err
if err:
raise CartError(err)
def update_tax_rates(event: Event, cart_id: str, invoice_address: InvoiceAddress):

View File

@@ -597,16 +597,16 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
except InvoiceAddress.DoesNotExist:
pass
# with event.lock() as now_dt:
now_dt = now()
positions = list(CartPosition.objects.filter(id__in=position_ids).select_related('item', 'variation', 'subevent'))
if len(positions) == 0:
raise OrderError(error_messages['empty'])
if len(position_ids) != len(positions):
raise OrderError(error_messages['internal'])
_check_positions(event, now_dt, positions, address=addr)
order = _create_order(event, email, positions, now_dt, pprov,
locale=locale, address=addr, meta_info=meta_info, sales_channel=sales_channel)
with event.lock() as now_dt:
positions = list(CartPosition.objects.filter(
id__in=position_ids).select_related('item', 'variation', 'subevent'))
if len(positions) == 0:
raise OrderError(error_messages['empty'])
if len(position_ids) != len(positions):
raise OrderError(error_messages['internal'])
_check_positions(event, now_dt, positions, address=addr)
order = _create_order(event, email, positions, now_dt, pprov,
locale=locale, address=addr, meta_info=meta_info, sales_channel=sales_channel)
invoice = order.invoices.last() # Might be generated by plugin already
if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order):

View File

@@ -31,12 +31,13 @@ def run_update_check(sender, **kwargs):
@app.task
def update_check():
gs = GlobalSettingsObject()
if not gs.settings.update_check_perform:
return
if not gs.settings.update_check_id:
gs.settings.set('update_check_id', uuid.uuid4().hex)
if not gs.settings.update_check_perform:
return
if 'runserver' in sys.argv:
gs.settings.set('update_check_last', now())
gs.settings.set('update_check_result', {

View File

@@ -78,6 +78,21 @@ def abslink_callback(attrs, new=False):
return attrs
def markdown_compile_email(source):
return bleach.linkify(bleach.clean(
markdown.markdown(
source,
extensions=[
'markdown.extensions.sane_lists',
# 'markdown.extensions.nl2br' # disabled for backwards-compatibility
]
),
tags=ALLOWED_TAGS,
attributes=ALLOWED_ATTRIBUTES,
protocols=ALLOWED_PROTOCOLS,
))
def markdown_compile(source):
return bleach.clean(
markdown.markdown(

View File

@@ -211,6 +211,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
'pretix.event.order.payment.started': _('Payment {local_id} has been started.'),
'pretix.event.order.payment.failed': _('Payment {local_id} has failed.'),
'pretix.event.order.quotaexceeded': _('The order could not be marked as paid: {message}'),
'pretix.event.order.overpaid': _('The order has been overpaid.'),
'pretix.event.order.refund.created': _('Refund {local_id} has been created.'),
'pretix.event.order.refund.created.externally': _('Refund {local_id} has been created by an external entity.'),
'pretix.event.order.refund.requested': _('The customer requested you to issue a refund.'),

View File

@@ -70,6 +70,7 @@
<a href="?{% url_replace request 'ordering' 'email'%}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "Name" %} <a href="?{% url_replace request 'ordering' '-name'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'name'%}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "Ticket code" %}</th>
<th>{% trans "Status" %} <a href="?{% url_replace request 'ordering' '-status'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'status'%}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "Timestamp" %} <a href="?{% url_replace request 'ordering' '-timestamp'%}"><i class="fa fa-caret-down"></i></a>
@@ -102,6 +103,9 @@
{{ e.attendee_name }}
{% endif %}
</td>
<td>
{{ e.secret|slice:":10" }}…
</td>
<td>
{% if not e.last_checked_in %}
<span class="label label-danger">{% trans "Not checked in" %}</span>

View File

@@ -22,13 +22,10 @@
<fieldset>
<legend>{% trans "E-mail preview" %}</legend>
<div class="tab-pane mail-preview-group">
<pre lang="" class="mail-preview">
{% for segment in preview_output %}
{% spaceless %}
{{ segment|linebreaksbr }}
{% endspaceless %}
{% endfor %}
</pre>
<div lang="{{ order.locale }}" class="mail-preview">
<strong>{{ preview_output.subject }}</strong><br><br>
{{ preview_output.html|safe }}
</div>
</div>
</fieldset>
{% endif %}

View File

@@ -85,7 +85,7 @@
</p>
{% endif %}
<div class="table-responsive">
<table class="table table-condensed table-hover">
<table class="table table-condensed table-hover table-orders">
<thead>
<tr>
<th>{% trans "Order code" %}
@@ -147,6 +147,32 @@
</tr>
{% endfor %}
</tbody>
{% if sums %}
<tfoot>
<tr>
<th>{% trans "Sum over all pages" %}</th>
<th></th>
<th>
{% blocktrans trimmed count s=sums.c %}
1 order
{% plural %}
{{ s }} orders
{% endblocktrans %}
</th>
<th class="text-right">
{% if sums.s|default_if_none:"none" != "none" %}
{{ sums.s|money:request.event.currency }}
{% endif %}
</th>
<th class="text-right">
{% if sums.pc %}
{{ sums.pc }}
{% endif %}
</th>
<th></th>
</tr>
</tfoot>
{% endif %}
</table>
</div>
{% include "pretixcontrol/pagination.html" %}

View File

@@ -158,7 +158,7 @@ class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
cl.subevent.event = self.request.event # re-use same event object to make sure settings are cached
cl.checkin_count = annotations.get(cl.pk, {}).get('checkin_count', 0)
cl.position_count = annotations.get(cl.pk, {}).get('position_count', 0)
cl.percent_count = annotations.get(cl.pk, {}).get('percent_count', 0)
cl.percent = annotations.get(cl.pk, {}).get('percent', 0)
ctx['checkinlists'] = clists
return ctx

View File

@@ -5,7 +5,6 @@ from datetime import timedelta
from decimal import Decimal
from urllib.parse import urlsplit
import bleach
from django.conf import settings
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
@@ -39,7 +38,7 @@ from pretix.base.services import tickets
from pretix.base.services.invoices import build_preview_invoice_pdf
from pretix.base.signals import register_ticket_outputs
from pretix.base.templatetags.money import money_filter
from pretix.base.templatetags.rich_text import markdown_compile
from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.control.forms.event import (
CancelSettingsForm, CommentForm, DisplaySettingsForm, EventDeleteForm,
EventMetaValueForm, EventSettingsForm, EventUpdateForm,
@@ -54,8 +53,8 @@ from pretix.multidomain.urlreverse import get_domain
from pretix.plugins.stripe.payment import StripeSettingsHolder
from pretix.presale.style import regenerate_css
from . import CreateView, PaginationMixin, UpdateView
from ..logdisplay import OVERVIEW_BLACKLIST
from . import CreateView, PaginationMixin, UpdateView
class EventSettingsViewMixin:
@@ -664,9 +663,9 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
idx = matched.group('idx')
if idx in self.supported_locale:
with translation.override(self.supported_locale[idx]):
msgs[self.supported_locale[idx]] = bleach.linkify(markdown_compile(
msgs[self.supported_locale[idx]] = markdown_compile_email(
v.format_map(self.placeholders(preview_item))
))
)
return JsonResponse({
'item': preview_item,

View File

@@ -12,7 +12,7 @@ from django.contrib import messages
from django.core.files import File
from django.db import transaction
from django.db.models import (
Count, IntegerField, OuterRef, ProtectedError, Subquery,
Count, IntegerField, OuterRef, ProtectedError, Q, Subquery, Sum,
)
from django.http import (
FileResponse, Http404, HttpResponseNotAllowed, JsonResponse,
@@ -60,6 +60,7 @@ from pretix.base.signals import (
register_data_exporters, register_ticket_outputs,
)
from pretix.base.templatetags.money import money_filter
from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.base.views.mixins import OrderQuestionsViewMixin
from pretix.base.views.tasks import AsyncAction
from pretix.control.forms.filter import EventOrderFilterForm, RefundFilterForm
@@ -125,6 +126,15 @@ class OrderList(EventPermissionRequiredMixin, PaginationMixin, ListView):
o.has_external_refund = annotated.get(o.pk)['has_external_refund']
o.has_pending_refund = annotated.get(o.pk)['has_pending_refund']
if ctx['page_obj'].paginator.count < 1000:
# Performance safeguard: Only count positions if the data set is small
ctx['sums'] = self.get_queryset().annotate(
pcnt=Subquery(s, output_field=IntegerField())
).aggregate(
s=Sum('total'), pc=Sum('pcnt'), c=Count('id')
)
else:
ctx['sums'] = self.get_queryset().aggregate(s=Sum('total'), c=Count('id'))
return ctx
@cached_property
@@ -1483,10 +1493,10 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView):
email_template = LazyI18nString(form.cleaned_data['message'])
email_content = render_mail(email_template, email_context)
if self.request.POST.get('action') == 'preview':
self.preview_output = []
self.preview_output.append(
_('Subject: {subject}').format(subject=form.cleaned_data['subject']))
self.preview_output.append(email_content)
self.preview_output = {
'subject': _('Subject: {subject}').format(subject=form.cleaned_data['subject']),
'html': markdown_compile_email(email_content)
}
return self.get(self.request, *self.args, **self.kwargs)
else:
try:
@@ -1601,6 +1611,13 @@ class OrderGo(EventPermissionRequiredMixin, View):
return redirect('control:event.order', event=request.event.slug, organizer=request.event.organizer.slug,
code=order.code)
except Order.DoesNotExist:
try:
i = self.request.event.invoices.get(Q(invoice_no=code) | Q(full_invoice_no=code))
return redirect('control:event.order', event=request.event.slug, organizer=request.event.organizer.slug,
code=i.order.code)
except Invoice.DoesNotExist:
pass
messages.error(request, _('There is no order with the given order code.'))
return redirect('control:event.orders', event=request.event.slug, organizer=request.event.organizer.slug)

View File

@@ -117,6 +117,7 @@ class SubEventDelete(EventPermissionRequiredMixin, DeleteView):
return HttpResponseRedirect(self.get_success_url())
else:
self.object.log_action('pretix.subevent.deleted', user=self.request.user)
self.object.cartposition_set.all().delete()
self.object.delete()
messages.success(request, pgettext_lazy('subevent', 'The selected date has been deleted.'))
return HttpResponseRedirect(success_url)

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -198,6 +198,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -197,6 +197,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-04-24 14:22+0000\n"
"Last-Translator: Pernille Thorsen <perth@aarhus.dk>\n"
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -214,6 +214,10 @@ msgstr "Ingen"
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Andre"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-12-02 15:44+0000\n"
"Last-Translator: Alexander Schwartz <alexander.schwartz@gmx.net>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -217,6 +217,10 @@ msgstr "Keine"
msgid "Use a different name internally"
msgstr "Intern einen anderen Namen verwenden"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Sonstige"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-12-02 13:41+0000\n"
"Last-Translator: Alexander Schwartz <alexander.schwartz@gmx.net>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
@@ -216,6 +216,10 @@ msgstr "Keine"
msgid "Use a different name internally"
msgstr "Intern einen anderen Namen verwenden"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Sonstige"

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+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"
@@ -198,6 +198,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -197,6 +197,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-02-20 03:00+0000\n"
"Last-Translator: oocf <oswaldocerna@gmail.com>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -218,6 +218,10 @@ msgstr "Ninguno"
msgid "Use a different name internally"
msgstr "Usar un nombre diferente internamente"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Otros"

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: French\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-10-28 10:23+0000\n"
"Last-Translator: Arnaud Vergnet <keplyx@gmail.com>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -219,6 +219,10 @@ msgstr "Aucun"
msgid "Use a different name internally"
msgstr "Utiliser un nom différent en interne"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Autres"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-01-02 08:20+0000\n"
"Last-Translator: amefad <fame@libero.it>\n"
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -212,6 +212,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-01-08 12:30+0000\n"
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -212,6 +212,10 @@ msgstr "Geen"
msgid "Use a different name internally"
msgstr "Gebruik intern een andere naam"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Andere"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -197,6 +197,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-01-08 21:00+0000\n"
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
@@ -214,6 +214,10 @@ msgstr "Geen"
msgid "Use a different name internally"
msgstr "Gebruik intern een andere naam"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Andere"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-10-22 04:23+0000\n"
"Last-Translator: Samir C. Costa <samirfor@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://translate.pretix.eu/projects/"
@@ -216,6 +216,10 @@ msgstr "Nenhum"
msgid "Use a different name internally"
msgstr "Use um nome diferente internamente"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Outros"

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-01-02 08:21+0000\n"
"Last-Translator: Alexey Zh <write2aracon@gmail.com>\n"
"Language-Team: Russian <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -200,6 +200,10 @@ msgstr ""
msgid "Use a different name internally"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-20 16:52+0000\n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2018-09-03 06:36+0000\n"
"Last-Translator: Yunus Fırat Pişkin <firat.piskin@idvlabs.com>\n"
"Language-Team: Turkish <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -216,6 +216,10 @@ msgstr "Hiçbiri"
msgid "Use a different name internally"
msgstr "Dahili olarak farklı bir ad kullan"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "Diğerleri"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,361 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-11 15:02+0000\n"
"PO-Revision-Date: 2019-03-09 14:00+0000\n"
"Last-Translator: yichengsd <sunzl@jxepub.com>\n"
"Language-Team: Chinese (Simplified) <https://translate.pretix.eu/projects/"
"pretix/pretix-js/zh_Hans/>\n"
"Language: zh_Hans\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 3.4\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:68
msgid "Marked as paid"
msgstr "标为已付款"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:76
msgid "Comment:"
msgstr "注释:"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
msgstr "提交的订单"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Paid orders"
msgstr "已付款订单"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
msgid "Total revenue"
msgstr "总收入"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
msgid "Contacting Stripe …"
msgstr "正在联系Stripe …"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:56
msgid "Total"
msgstr "总计"
#: pretix/static/pretixbase/js/asynctask.js:39
#: pretix/static/pretixbase/js/asynctask.js:95
msgid ""
"Your request has been queued on the server and will now be processed. "
"Depending on the size of your event, this might take up to a few minutes."
msgstr ""
"您的请求已经在服务器上排队,现在将被处理。根据活动规模,这可能需要几分钟的时"
"间。"
#: pretix/static/pretixbase/js/asynctask.js:45
#: pretix/static/pretixbase/js/asynctask.js:101
msgid ""
"Your request arrived on the server but we still wait for it to be processed. "
"If this takes longer than two minutes, please contact us or go back in your "
"browser and try again."
msgstr ""
"您的请求已提交到服务器,但仍在等待处理。如果等待超过两分钟,请与我们联系或返"
"回您的浏览器再试一次。"
#: pretix/static/pretixbase/js/asynctask.js:66
#: pretix/static/pretixbase/js/asynctask.js:124
#: pretix/static/pretixcontrol/js/ui/mail.js:23
msgid "An error of type {code} occurred."
msgstr "发生类型为{code}的错误。"
#: pretix/static/pretixbase/js/asynctask.js:69
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
msgstr "我们目前无法连接到服务器,但我们一直在尝试。最后的错误代码为:{code}"
#: pretix/static/pretixbase/js/asynctask.js:115
#: pretix/static/pretixcontrol/js/ui/mail.js:20
msgid "The request took to long. Please try again."
msgstr "服务器请求超时。请再试一次。"
#: pretix/static/pretixbase/js/asynctask.js:127
#: pretix/static/pretixcontrol/js/ui/mail.js:25
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
msgstr "我们目前无法连接到服务器。请再试一次。错误代码为:{code}"
#: pretix/static/pretixbase/js/asynctask.js:148
msgid "We are processing your request …"
msgstr "我们正在处理你的请求…"
#: pretix/static/pretixbase/js/asynctask.js:156
msgid ""
"We are currently sending your request to the server. If this takes longer "
"than one minute, please check your internet connection and then reload this "
"page and try again."
msgstr ""
"我们正在将您的请求发送到服务器。如果超过一分钟,请检查您的互联网连接,然后刷"
"新此页面,并重试。"
#: pretix/static/pretixbase/js/asynctask.js:193
#: pretix/static/pretixcontrol/js/ui/main.js:28
msgid "Close message"
msgstr "关闭消息"
#: pretix/static/pretixcontrol/js/clipboard.js:23
msgid "Copied!"
msgstr "已复制!"
#: pretix/static/pretixcontrol/js/clipboard.js:29
msgid "Press Ctrl-C to copy!"
msgstr "按Ctrl-C复制!"
#: pretix/static/pretixcontrol/js/ui/editor.js:43
msgid "Lead Scan QR"
msgstr "导入扫描QR码"
#: pretix/static/pretixcontrol/js/ui/editor.js:45
msgid "Check-in QR"
msgstr "签到QR码"
#: pretix/static/pretixcontrol/js/ui/editor.js:249
msgid "The PDF background file could not be loaded for the following reason:"
msgstr "由于以下原因无法加载PDF背景文件:"
#: pretix/static/pretixcontrol/js/ui/editor.js:418
msgid "Group of objects"
msgstr "对象组"
#: pretix/static/pretixcontrol/js/ui/editor.js:424
msgid "Text object"
msgstr "文本对象"
#: pretix/static/pretixcontrol/js/ui/editor.js:426
msgid "Barcode area"
msgstr "条码区"
#: pretix/static/pretixcontrol/js/ui/editor.js:428
msgid "Powered by pretix"
msgstr "由pretix驱动"
#: pretix/static/pretixcontrol/js/ui/editor.js:430
msgid "Object"
msgstr "对象"
#: pretix/static/pretixcontrol/js/ui/editor.js:434
msgid "Ticket design"
msgstr "门票设计"
#: pretix/static/pretixcontrol/js/ui/editor.js:687
msgid "Saving failed."
msgstr "保存失败."
#: pretix/static/pretixcontrol/js/ui/editor.js:735
msgid "Do you really want to leave the editor without saving your changes?"
msgstr "你真的想离开编辑器而不保存你的更改吗?"
#: pretix/static/pretixcontrol/js/ui/editor.js:749
msgid "Error while uploading your PDF file, please try again."
msgstr "上传PDF文件时出错请重试。"
#: pretix/static/pretixcontrol/js/ui/mail.js:18
msgid "An error has occurred."
msgstr "发生一个错误。"
#: pretix/static/pretixcontrol/js/ui/mail.js:52
msgid "Generating messages …"
msgstr "生成消息…"
#: pretix/static/pretixcontrol/js/ui/main.js:43
msgid "Unknown error."
msgstr "未知错误。"
#: pretix/static/pretixcontrol/js/ui/main.js:205
msgid "Your color has great contrast and is very easy to read!"
msgstr "你的配色有很高的对比度,非常易读!"
#: pretix/static/pretixcontrol/js/ui/main.js:209
msgid "Your color has decent contrast and is probably good-enough to read!"
msgstr "你的配色有很好的对比度,可能足够易读!"
#: pretix/static/pretixcontrol/js/ui/main.js:213
msgid ""
"Your color has bad contrast for text on white background, please choose a "
"darker shade."
msgstr "你的配色在白色背景下的文本对比度很差,请选择较深的颜色。"
#: pretix/static/pretixcontrol/js/ui/main.js:294
msgid "All"
msgstr "所有"
#: pretix/static/pretixcontrol/js/ui/main.js:295
msgid "None"
msgstr "无"
#: pretix/static/pretixcontrol/js/ui/main.js:588
msgid "Use a different name internally"
msgstr "在内部使用一个不同的名称"
#: pretix/static/pretixcontrol/js/ui/main.js:639
msgid "Click to close"
msgstr ""
#: pretix/static/pretixcontrol/js/ui/question.js:41
msgid "Others"
msgstr "其他"
#: pretix/static/pretixcontrol/js/ui/question.js:70
msgid "Count"
msgstr "数量"
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
msgid "(one more date)"
msgid_plural "({num} more dates)"
msgstr[0] "(一个以上日期)"
#: pretix/static/pretixpresale/js/ui/cart.js:39
msgid "The items in your cart are no longer reserved for you."
msgstr "你购物车里的物品将不再为你保留。"
#: pretix/static/pretixpresale/js/ui/cart.js:41
msgid "Cart expired"
msgstr "购物车已过期"
#: pretix/static/pretixpresale/js/ui/cart.js:46
msgid "The items in your cart are reserved for you for one minute."
msgid_plural "The items in your cart are reserved for you for {num} minutes."
msgstr[0] "购物车中的物品将为您保留{num}分钟。"
#: pretix/static/pretixpresale/js/widget/widget.js:14
msgctxt "widget"
msgid "Sold out"
msgstr "已售空"
#: pretix/static/pretixpresale/js/widget/widget.js:15
msgctxt "widget"
msgid "Buy"
msgstr "购买"
#: pretix/static/pretixpresale/js/widget/widget.js:16
msgctxt "widget"
msgid "Reserved"
msgstr "保留"
#: pretix/static/pretixpresale/js/widget/widget.js:17
msgctxt "widget"
msgid "FREE"
msgstr "免费"
#: pretix/static/pretixpresale/js/widget/widget.js:18
msgctxt "widget"
msgid "from %(currency)s %(price)s"
msgstr "由 %(currency)s %(price)s"
#: pretix/static/pretixpresale/js/widget/widget.js:19
msgctxt "widget"
msgid "incl. %(rate)s% %(taxname)s"
msgstr "包含 %(rate)s% %(taxname)s"
#: pretix/static/pretixpresale/js/widget/widget.js:20
msgctxt "widget"
msgid "plus %(rate)s% %(taxname)s"
msgstr "另加 %(rate)s% %(taxname)s"
#: pretix/static/pretixpresale/js/widget/widget.js:21
#, javascript-format
msgctxt "widget"
msgid "currently available: %s"
msgstr "当前可用: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:22
msgctxt "widget"
msgid "Only available with a voucher"
msgstr "只能凭券购买"
#: pretix/static/pretixpresale/js/widget/widget.js:23
#, javascript-format
msgctxt "widget"
msgid "minimum amount to order: %s"
msgstr "最低订购量: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:24
msgctxt "widget"
msgid "Close ticket shop"
msgstr "关闭售票"
#: pretix/static/pretixpresale/js/widget/widget.js:25
msgctxt "widget"
msgid "The ticket shop could not be loaded."
msgstr "无法加载售票厅。"
#: pretix/static/pretixpresale/js/widget/widget.js:26
msgctxt "widget"
msgid "The cart could not be created. Please try again later"
msgstr "无法创建购物车。请稍后再试"
#: pretix/static/pretixpresale/js/widget/widget.js:27
msgctxt "widget"
msgid "Waiting list"
msgstr "候补列表"
#: pretix/static/pretixpresale/js/widget/widget.js:28
msgctxt "widget"
msgid ""
"You currently have an active cart for this event. If you select more "
"products, they will be added to your existing cart."
msgstr ""
"您当前有一个本次活动的购物车。如果您选择更多的产品,它们将被添加到您现有的购"
"物车中。"
#: pretix/static/pretixpresale/js/widget/widget.js:30
msgctxt "widget"
msgid "Resume checkout"
msgstr "继续结账"
#: pretix/static/pretixpresale/js/widget/widget.js:31
msgctxt "widget"
msgid ""
"<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
"ticketing powered by pretix</a>"
msgstr ""
"<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">票务由pretix"
"驱动</a>"
#: pretix/static/pretixpresale/js/widget/widget.js:33
msgctxt "widget"
msgid "Redeem a voucher"
msgstr "兑换优惠券"
#: pretix/static/pretixpresale/js/widget/widget.js:34
msgctxt "widget"
msgid "Redeem"
msgstr "兑换"
#: pretix/static/pretixpresale/js/widget/widget.js:35
msgctxt "widget"
msgid "Voucher code"
msgstr "优惠券代码"
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"
msgid "Close"
msgstr "关闭"
#: pretix/static/pretixpresale/js/widget/widget.js:37
msgctxt "widget"
msgid "Continue"
msgstr "继续"
#: pretix/static/pretixpresale/js/widget/widget.js:38
msgctxt "widget"
msgid "See variations"
msgstr "查看变化"

View File

@@ -6,7 +6,13 @@ from pretix.api.serializers.order import CompatibleJSONField
from .models import BadgeItem, BadgeLayout
class ItemAssignmentSerializer(I18nAwareModelSerializer):
class BadgeItemAssignmentSerializer(I18nAwareModelSerializer):
class Meta:
model = BadgeItem
fields = ('id', 'item', 'layout')
class NestedItemAssignmentSerializer(I18nAwareModelSerializer):
class Meta:
model = BadgeItem
fields = ('item',)
@@ -14,7 +20,7 @@ class ItemAssignmentSerializer(I18nAwareModelSerializer):
class BadgeLayoutSerializer(I18nAwareModelSerializer):
layout = CompatibleJSONField()
item_assignments = ItemAssignmentSerializer(many=True)
item_assignments = NestedItemAssignmentSerializer(many=True)
class Meta:
model = BadgeLayout
@@ -28,3 +34,12 @@ class BadgeLayoutViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return self.request.event.badge_layouts.all()
class BadgeItemViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = BadgeItemAssignmentSerializer
queryset = BadgeItem.objects.none()
lookup_field = 'id'
def get_queryset(self):
return BadgeItem.objects.filter(item__event=self.request.event)

View File

@@ -1,7 +1,7 @@
from django.conf.urls import url
from pretix.api.urls import event_router
from pretix.plugins.badges.api import BadgeLayoutViewSet
from pretix.plugins.badges.api import BadgeItemViewSet, BadgeLayoutViewSet
from .views import (
LayoutCreate, LayoutDelete, LayoutEditorView, LayoutListView,
@@ -23,3 +23,4 @@ urlpatterns = [
LayoutEditorView.as_view(), name='edit'),
]
event_router.register('badgelayouts', BadgeLayoutViewSet)
event_router.register('badgeitems', BadgeItemViewSet)

View File

@@ -46,6 +46,10 @@ def get_rows_from_file(file):
except ImportError:
charset = file.charset
data = data.decode(charset or 'utf-8')
# If the file was modified on a Mac, it only contains \r as line breaks
if '\r' in data and '\n' not in data:
data = data.replace('\r', '\n')
# Sniffing line by line is necessary as some banks like to include
# one-column garbage at the beginning of the file which breaks the sniffer.
# See also: http://bugs.python.org/issue2078

View File

@@ -228,7 +228,8 @@ def webhook(request, *args, **kwargs):
payment.create_external_refund(
amount=payment.amount - known_sum
)
elif payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED) and sale['state'] == 'completed':
elif payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED,
OrderPayment.PAYMENT_STATE_CANCELED, OrderPayment.PAYMENT_STATE_FAILED) and sale['state'] == 'completed':
try:
payment.confirm()
except Quota.QuotaExceededException:

View File

@@ -12,11 +12,13 @@ class MailForm(forms.Form):
sendto = forms.MultipleChoiceField() # overridden later
subject = forms.CharField(label=_("Subject"))
message = forms.CharField(label=_("Message"))
item = forms.ModelChoiceField(
Item.objects.none(),
items = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple(
attrs={'class': 'scrolling-multiple-choice'}
),
label=_('Only send to people who bought'),
required=False,
empty_label=_('Any product')
required=True,
queryset=Item.objects.none()
)
subevent = forms.ModelChoiceField(
SubEvent.objects.none(),
@@ -53,10 +55,18 @@ class MailForm(forms.Form):
)
self.fields['sendto'] = forms.MultipleChoiceField(
label=_("Send to customers with order status"),
widget=forms.CheckboxSelectMultiple,
widget=forms.CheckboxSelectMultiple(
attrs={'class': 'scrolling-multiple-choice'}
),
choices=choices
)
self.fields['item'].queryset = event.items.all()
if not self.initial.get('sendto'):
self.initial['sendto'] = ['p', 'n']
self.fields['items'].queryset = event.items.all()
if not self.initial.get('items'):
self.initial['items'] = event.items.all()
if event.has_subevents:
self.fields['subevent'].queryset = event.subevents.all()
self.fields['subevent'].widget = Select2(

View File

@@ -16,10 +16,13 @@
{% if log.display %}
<br/><span class="fa fa-comment-o fa-fw"></span> {{ log.display }}
{% endif %}
<br/><span class="fa fa-shopping-cart fa-fw"></span> {% trans "Sent to orders:" %}
<br/><span class="fa fa-tag fa-fw"></span> {% trans "Sent to orders:" %}
{% for status in log.parsed_data.sendto %}
{{ status }}{% if forloop.revcounter > 1 %},{% endif %}
{% endfor %}
{% if log.pdata.items %}
<br/><span class="fa fa-shopping-cart fa-fw"></span> {{ log.pdata.items|join:", " }}
{% endif %}
{% if log.pdata.subevent_obj %}
<br/><span class="fa fa-calendar fa-fw"></span> {{ log.pdata.subevent_obj }}
{% endif %}

View File

@@ -11,19 +11,18 @@
{% if form.subevent %}
{% bootstrap_field form.subevent layout='horizontal' %}
{% endif %}
{% bootstrap_field form.item layout='horizontal' %}
{% bootstrap_field form.items layout='horizontal' %}
{% bootstrap_field form.subject layout='horizontal' %}
{% bootstrap_field form.message layout='horizontal' %}
{% if request.method == "POST" %}
<fieldset>
<legend>{% trans "E-mail preview" %}</legend>
<div class="tab-pane mail-preview-group">
{% for locale, segments in output.items %}
<pre lang="{{ locale }}" class="mail-preview">{% spaceless %}
{% for value in segments %}
{{ value|linebreaksbr }}
{% endfor %}
{% endspaceless %}</pre>
{% for locale, out in output.items %}
<div lang="{{ locale }}" class="mail-preview">
<strong>{{ out.subject }}</strong><br><br>
{{ out.html|safe }}
</div>
{% endfor %}
</div>
</fieldset>

View File

@@ -13,6 +13,7 @@ from django.views.generic import FormView, ListView
from pretix.base.i18n import LazyI18nString, language
from pretix.base.models import LogEntry, Order
from pretix.base.models.event import SubEvent
from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.control.permissions import EventPermissionRequiredMixin
from pretix.multidomain.urlreverse import build_absolute_uri
from pretix.plugins.sendmail.tasks import send_mails
@@ -43,6 +44,14 @@ class SenderView(EventPermissionRequiredMixin, FormView):
'subject': LazyI18nString(logentry.parsed_data['subject']),
'sendto': logentry.parsed_data['sendto'],
}
if 'items' in logentry.parsed_data:
kwargs['initial']['items'] = self.request.event.items.filter(
id__in=[a['id'] for a in logentry.parsed_data['items']]
)
elif logentry.parsed_data.get('item'):
kwargs['initial']['items'] = self.request.event.items.filter(
id=logentry.parsed_data['item']['id']
)
if logentry.parsed_data.get('subevent'):
try:
kwargs['initial']['subevent'] = self.request.event.subevents.get(
@@ -64,9 +73,8 @@ class SenderView(EventPermissionRequiredMixin, FormView):
if 'overdue' in form.cleaned_data['sendto']:
statusq |= Q(status=Order.STATUS_PENDING, expires__lt=now())
orders = qs.filter(statusq)
if form.cleaned_data.get('item'):
orders = orders.filter(all_positions__item=form.cleaned_data.get('item'),
all_positions__canceled=False)
orders = orders.filter(all_positions__item_id__in=[i.pk for i in form.cleaned_data.get('items')],
all_positions__canceled=False)
if form.cleaned_data.get('subevent'):
orders = orders.filter(all_positions__subevent__in=(form.cleaned_data.get('subevent'),),
all_positions__canceled=False)
@@ -95,16 +103,15 @@ class SenderView(EventPermissionRequiredMixin, FormView):
'invoice_company': _('Sample Company LLC')
}
self.output[l] = []
subject = form.cleaned_data['subject'].localize(l)
preview_subject = subject.format_map(context_dict)
self.output[l].append(
_('Subject: {subject}').format(subject=preview_subject))
message = form.cleaned_data['message'].localize(l)
preview_text = message.format_map(context_dict)
self.output[l].append(preview_text)
preview_text = markdown_compile_email(message.format_map(context_dict))
self.output[l] = {
'subject': _('Subject: {subject}').format(subject=preview_subject),
'html': preview_text,
}
return self.get(self.request, *self.args, **self.kwargs)
@@ -145,12 +152,15 @@ class EmailHistoryView(EventPermissionRequiredMixin, ListView):
qs = LogEntry.objects.filter(
event=self.request.event,
action_type='pretix.plugins.sendmail.sent'
)
).select_related('event', 'user')
return qs
def get_context_data(self, **kwargs):
ctx = super().get_context_data()
itemcache = {
i.pk: str(i) for i in self.request.event.items.all()
}
status = dict(Order.STATUS_CHOICE)
status['overdue'] = _('pending with payment overdue')
status['r'] = status['c']
@@ -165,6 +175,9 @@ class EmailHistoryView(EventPermissionRequiredMixin, ListView):
log.pdata['sendto'] = [
status[s] for s in log.pdata['sendto']
]
log.pdata['items'] = [
itemcache[i['id']] for i in log.pdata.get('items', [])
]
if log.pdata.get('subevent'):
try:
log.pdata['subevent_obj'] = self.request.event.subevents.get(pk=log.pdata['subevent']['id'])

View File

@@ -8,6 +8,13 @@ from .models import TicketLayout, TicketLayoutItem
class ItemAssignmentSerializer(I18nAwareModelSerializer):
class Meta:
model = TicketLayoutItem
fields = ('id', 'layout', 'item', 'sales_channel')
class NestedItemAssignmentSerializer(I18nAwareModelSerializer):
class Meta:
model = TicketLayoutItem
fields = ('item', 'sales_channel')
@@ -15,7 +22,7 @@ class ItemAssignmentSerializer(I18nAwareModelSerializer):
class TicketLayoutSerializer(I18nAwareModelSerializer):
layout = CompatibleJSONField()
item_assignments = ItemAssignmentSerializer(many=True)
item_assignments = NestedItemAssignmentSerializer(many=True)
class Meta:
model = TicketLayout
@@ -29,3 +36,12 @@ class TicketLayoutViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return self.request.event.ticket_layouts.all()
class TicketLayoutItemViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = ItemAssignmentSerializer
queryset = TicketLayoutItem.objects.none()
lookup_field = 'id'
def get_queryset(self):
return TicketLayoutItem.objects.filter(item__event=self.request.event)

View File

@@ -1,7 +1,9 @@
from django.conf.urls import url
from pretix.api.urls import event_router
from pretix.plugins.ticketoutputpdf.api import TicketLayoutViewSet
from pretix.plugins.ticketoutputpdf.api import (
TicketLayoutItemViewSet, TicketLayoutViewSet,
)
from pretix.plugins.ticketoutputpdf.views import (
LayoutCreate, LayoutDelete, LayoutEditorView, LayoutGetDefault,
LayoutListView, LayoutSetDefault,
@@ -22,3 +24,4 @@ urlpatterns = [
LayoutEditorView.as_view(), name='edit'),
]
event_router.register('ticketlayouts', TicketLayoutViewSet)
event_router.register('ticketlayoutitems', TicketLayoutItemViewSet)

View File

@@ -12,9 +12,9 @@ from pretix.base.templatetags.urlreplace import url_replace
from pretix.multidomain.urlreverse import eventreverse
from pretix.presale.views import EventViewMixin
from . import allow_frame_if_namespaced
from ...base.models import Item, ItemVariation, WaitingListEntry
from ..forms.waitinglist import WaitingListForm
from . import allow_frame_if_namespaced
@method_decorator(allow_frame_if_namespaced, 'dispatch')

View File

@@ -179,10 +179,6 @@ METRICS_PASSPHRASE = config.get('metrics', 'passphrase', fallback="")
CACHES = {
'default': {
'BACKEND': 'pretix.helpers.cache.CustomDummyCache',
},
'file': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/tmp/django_cache',
}
}
REAL_CACHE_USED = False
@@ -493,8 +489,6 @@ COMPRESS_PRECOMPILERS = (
COMPRESS_ENABLED = COMPRESS_OFFLINE = not debug_fallback
COMPRESS_CACHE_BACKEND = 'file'
COMPRESS_CSS_FILTERS = (
# CssAbsoluteFilter is incredibly slow, especially when dealing with our _flags.scss
# However, we don't need it if we consequently use the static() function in Sass

View File

@@ -157,6 +157,12 @@
-webkit-box-shadow: none;
}
.pagination > li.page-current > a:hover, .pagination > li.page-current > a:focus {
color: #7f5a91;
background-color: #fff;
border: 1px solid #ddd;
}
@include table-row-variant('success', lighten($brand-success, 40%));
@include table-row-variant('info', lighten($brand-info, 30%));
@include table-row-variant('warning', lighten($brand-warning, 40%));

View File

@@ -12,250 +12,256 @@ pre[lang] {
padding-top: 8px;
margin-bottom: 20px;
}
div[lang] {
background: no-repeat 10px 12px;
padding-left: 34px;
padding-top: 8px;
min-height: 30px;
}
pre[lang=ad], input[lang=ad], textarea[lang=ad] { background-image: url(static('pretixbase/img/flags/ad.png')); }
pre[lang=ae], input[lang=ae], textarea[lang=ae] { background-image: url(static('pretixbase/img/flags/ae.png')); }
pre[lang=af], input[lang=af], textarea[lang=af] { background-image: url(static('pretixbase/img/flags/af.png')); }
pre[lang=ag], input[lang=ag], textarea[lang=ag] { background-image: url(static('pretixbase/img/flags/ag.png')); }
pre[lang=ai], input[lang=ai], textarea[lang=ai] { background-image: url(static('pretixbase/img/flags/ai.png')); }
pre[lang=al], input[lang=al], textarea[lang=al] { background-image: url(static('pretixbase/img/flags/al.png')); }
pre[lang=am], input[lang=am], textarea[lang=am] { background-image: url(static('pretixbase/img/flags/am.png')); }
pre[lang=an], input[lang=an], textarea[lang=an] { background-image: url(static('pretixbase/img/flags/an.png')); }
pre[lang=ao], input[lang=ao], textarea[lang=ao] { background-image: url(static('pretixbase/img/flags/ao.png')); }
pre[lang=ar], input[lang=ar], textarea[lang=ar] { background-image: url(static('pretixbase/img/flags/ar.png')); }
pre[lang=as], input[lang=as], textarea[lang=as] { background-image: url(static('pretixbase/img/flags/as.png')); }
pre[lang=at], input[lang=at], textarea[lang=at] { background-image: url(static('pretixbase/img/flags/at.png')); }
pre[lang=au], input[lang=au], textarea[lang=au] { background-image: url(static('pretixbase/img/flags/au.png')); }
pre[lang=aw], input[lang=aw], textarea[lang=aw] { background-image: url(static('pretixbase/img/flags/aw.png')); }
pre[lang=ax], input[lang=ax], textarea[lang=ax] { background-image: url(static('pretixbase/img/flags/ax.png')); }
pre[lang=az], input[lang=az], textarea[lang=az] { background-image: url(static('pretixbase/img/flags/az.png')); }
pre[lang=ba], input[lang=ba], textarea[lang=ba] { background-image: url(static('pretixbase/img/flags/ba.png')); }
pre[lang=bb], input[lang=bb], textarea[lang=bb] { background-image: url(static('pretixbase/img/flags/bb.png')); }
pre[lang=bd], input[lang=bd], textarea[lang=bd] { background-image: url(static('pretixbase/img/flags/bd.png')); }
pre[lang=be], input[lang=be], textarea[lang=be] { background-image: url(static('pretixbase/img/flags/be.png')); }
pre[lang=bf], input[lang=bf], textarea[lang=bf] { background-image: url(static('pretixbase/img/flags/bf.png')); }
pre[lang=bg], input[lang=bg], textarea[lang=bg] { background-image: url(static('pretixbase/img/flags/bg.png')); }
pre[lang=bh], input[lang=bh], textarea[lang=bh] { background-image: url(static('pretixbase/img/flags/bh.png')); }
pre[lang=bi], input[lang=bi], textarea[lang=bi] { background-image: url(static('pretixbase/img/flags/bi.png')); }
pre[lang=bj], input[lang=bj], textarea[lang=bj] { background-image: url(static('pretixbase/img/flags/bj.png')); }
pre[lang=bm], input[lang=bm], textarea[lang=bm] { background-image: url(static('pretixbase/img/flags/bm.png')); }
pre[lang=bn], input[lang=bn], textarea[lang=bn] { background-image: url(static('pretixbase/img/flags/bn.png')); }
pre[lang=bo], input[lang=bo], textarea[lang=bo] { background-image: url(static('pretixbase/img/flags/bo.png')); }
pre[lang=br], input[lang=br], textarea[lang=br] { background-image: url(static('pretixbase/img/flags/br.png')); }
pre[lang=pt-br], input[lang=pt-br], textarea[lang=pt-br] { background-image: url(static('pretixbase/img/flags/br.png')); }
pre[lang=bs], input[lang=bs], textarea[lang=bs] { background-image: url(static('pretixbase/img/flags/bs.png')); }
pre[lang=bt], input[lang=bt], textarea[lang=bt] { background-image: url(static('pretixbase/img/flags/bt.png')); }
pre[lang=bv], input[lang=bv], textarea[lang=bv] { background-image: url(static('pretixbase/img/flags/bv.png')); }
pre[lang=bw], input[lang=bw], textarea[lang=bw] { background-image: url(static('pretixbase/img/flags/bw.png')); }
pre[lang=by], input[lang=by], textarea[lang=by] { background-image: url(static('pretixbase/img/flags/by.png')); }
pre[lang=bz], input[lang=bz], textarea[lang=bz] { background-image: url(static('pretixbase/img/flags/bz.png')); }
pre[lang=ca], input[lang=ca], textarea[lang=ca] { background-image: url(static('pretixbase/img/flags/ca.png')); }
pre[lang=cc], input[lang=cc], textarea[lang=cc] { background-image: url(static('pretixbase/img/flags/cc.png')); }
pre[lang=cd], input[lang=cd], textarea[lang=cd] { background-image: url(static('pretixbase/img/flags/cd.png')); }
pre[lang=cf], input[lang=cf], textarea[lang=cf] { background-image: url(static('pretixbase/img/flags/cf.png')); }
pre[lang=cg], input[lang=cg], textarea[lang=cg] { background-image: url(static('pretixbase/img/flags/cg.png')); }
pre[lang=ch], input[lang=ch], textarea[lang=ch] { background-image: url(static('pretixbase/img/flags/ch.png')); }
pre[lang=ci], input[lang=ci], textarea[lang=ci] { background-image: url(static('pretixbase/img/flags/ci.png')); }
pre[lang=ck], input[lang=ck], textarea[lang=ck] { background-image: url(static('pretixbase/img/flags/ck.png')); }
pre[lang=cl], input[lang=cl], textarea[lang=cl] { background-image: url(static('pretixbase/img/flags/cl.png')); }
pre[lang=cm], input[lang=cm], textarea[lang=cm] { background-image: url(static('pretixbase/img/flags/cm.png')); }
pre[lang=cn], input[lang=cn], textarea[lang=cn] { background-image: url(static('pretixbase/img/flags/cn.png')); }
pre[lang=co], input[lang=co], textarea[lang=co] { background-image: url(static('pretixbase/img/flags/co.png')); }
pre[lang=cr], input[lang=cr], textarea[lang=cr] { background-image: url(static('pretixbase/img/flags/cr.png')); }
pre[lang=cs], input[lang=cs], textarea[lang=cs] { background-image: url(static('pretixbase/img/flags/cs.png')); }
pre[lang=cu], input[lang=cu], textarea[lang=cu] { background-image: url(static('pretixbase/img/flags/cu.png')); }
pre[lang=cv], input[lang=cv], textarea[lang=cv] { background-image: url(static('pretixbase/img/flags/cv.png')); }
pre[lang=cx], input[lang=cx], textarea[lang=cx] { background-image: url(static('pretixbase/img/flags/cx.png')); }
pre[lang=cy], input[lang=cy], textarea[lang=cy] { background-image: url(static('pretixbase/img/flags/cy.png')); }
pre[lang=cz], input[lang=cz], textarea[lang=cz] { background-image: url(static('pretixbase/img/flags/cz.png')); }
pre[lang=de], input[lang=de], textarea[lang=de] { background-image: url(static('pretixbase/img/flags/de.png')); }
pre[lang=de-informal], input[lang=de-informal], textarea[lang=de-informal] { background-image: url(static('pretixbase/img/flags/de-informal.png')); }
pre[lang=dj], input[lang=dj], textarea[lang=dj] { background-image: url(static('pretixbase/img/flags/dj.png')); }
pre[lang=da], input[lang=da], textarea[lang=da] { background-image: url(static('pretixbase/img/flags/dk.png')); }
pre[lang=dk], input[lang=dk], textarea[lang=dk] { background-image: url(static('pretixbase/img/flags/dk.png')); }
pre[lang=dm], input[lang=dm], textarea[lang=dm] { background-image: url(static('pretixbase/img/flags/dm.png')); }
pre[lang=do], input[lang=do], textarea[lang=do] { background-image: url(static('pretixbase/img/flags/do.png')); }
pre[lang=dz], input[lang=dz], textarea[lang=dz] { background-image: url(static('pretixbase/img/flags/dz.png')); }
pre[lang=ec], input[lang=ec], textarea[lang=ec] { background-image: url(static('pretixbase/img/flags/ec.png')); }
pre[lang=ee], input[lang=ee], textarea[lang=ee] { background-image: url(static('pretixbase/img/flags/ee.png')); }
pre[lang=eg], input[lang=eg], textarea[lang=eg] { background-image: url(static('pretixbase/img/flags/eg.png')); }
pre[lang=eh], input[lang=eh], textarea[lang=eh] { background-image: url(static('pretixbase/img/flags/eh.png')); }
pre[lang=er], input[lang=er], textarea[lang=er] { background-image: url(static('pretixbase/img/flags/er.png')); }
pre[lang=es], input[lang=es], textarea[lang=es] { background-image: url(static('pretixbase/img/flags/es.png')); }
pre[lang=et], input[lang=et], textarea[lang=et] { background-image: url(static('pretixbase/img/flags/et.png')); }
pre[lang=fi], input[lang=fi], textarea[lang=fi] { background-image: url(static('pretixbase/img/flags/fi.png')); }
pre[lang=fj], input[lang=fj], textarea[lang=fj] { background-image: url(static('pretixbase/img/flags/fj.png')); }
pre[lang=fk], input[lang=fk], textarea[lang=fk] { background-image: url(static('pretixbase/img/flags/fk.png')); }
pre[lang=fm], input[lang=fm], textarea[lang=fm] { background-image: url(static('pretixbase/img/flags/fm.png')); }
pre[lang=fo], input[lang=fo], textarea[lang=fo] { background-image: url(static('pretixbase/img/flags/fo.png')); }
pre[lang=fr], input[lang=fr], textarea[lang=fr] { background-image: url(static('pretixbase/img/flags/fr.png')); }
pre[lang=ga], input[lang=ga], textarea[lang=ga] { background-image: url(static('pretixbase/img/flags/ga.png')); }
pre[lang=gb], input[lang=gb], textarea[lang=gb] { background-image: url(static('pretixbase/img/flags/gb.png')); }
pre[lang=gd], input[lang=gd], textarea[lang=gd] { background-image: url(static('pretixbase/img/flags/gd.png')); }
pre[lang=ge], input[lang=ge], textarea[lang=ge] { background-image: url(static('pretixbase/img/flags/ge.png')); }
pre[lang=gf], input[lang=gf], textarea[lang=gf] { background-image: url(static('pretixbase/img/flags/gf.png')); }
pre[lang=gh], input[lang=gh], textarea[lang=gh] { background-image: url(static('pretixbase/img/flags/gh.png')); }
pre[lang=gi], input[lang=gi], textarea[lang=gi] { background-image: url(static('pretixbase/img/flags/gi.png')); }
pre[lang=gl], input[lang=gl], textarea[lang=gl] { background-image: url(static('pretixbase/img/flags/gl.png')); }
pre[lang=gm], input[lang=gm], textarea[lang=gm] { background-image: url(static('pretixbase/img/flags/gm.png')); }
pre[lang=gn], input[lang=gn], textarea[lang=gn] { background-image: url(static('pretixbase/img/flags/gn.png')); }
pre[lang=gp], input[lang=gp], textarea[lang=gp] { background-image: url(static('pretixbase/img/flags/gp.png')); }
pre[lang=gq], input[lang=gq], textarea[lang=gq] { background-image: url(static('pretixbase/img/flags/gq.png')); }
pre[lang=gr], input[lang=gr], textarea[lang=gr] { background-image: url(static('pretixbase/img/flags/gr.png')); }
pre[lang=gs], input[lang=gs], textarea[lang=gs] { background-image: url(static('pretixbase/img/flags/gs.png')); }
pre[lang=gt], input[lang=gt], textarea[lang=gt] { background-image: url(static('pretixbase/img/flags/gt.png')); }
pre[lang=gu], input[lang=gu], textarea[lang=gu] { background-image: url(static('pretixbase/img/flags/gu.png')); }
pre[lang=gw], input[lang=gw], textarea[lang=gw] { background-image: url(static('pretixbase/img/flags/gw.png')); }
pre[lang=gy], input[lang=gy], textarea[lang=gy] { background-image: url(static('pretixbase/img/flags/gy.png')); }
pre[lang=hk], input[lang=hk], textarea[lang=hk] { background-image: url(static('pretixbase/img/flags/hk.png')); }
pre[lang=hm], input[lang=hm], textarea[lang=hm] { background-image: url(static('pretixbase/img/flags/hm.png')); }
pre[lang=hn], input[lang=hn], textarea[lang=hn] { background-image: url(static('pretixbase/img/flags/hn.png')); }
pre[lang=hr], input[lang=hr], textarea[lang=hr] { background-image: url(static('pretixbase/img/flags/hr.png')); }
pre[lang=ht], input[lang=ht], textarea[lang=ht] { background-image: url(static('pretixbase/img/flags/ht.png')); }
pre[lang=hu], input[lang=hu], textarea[lang=hu] { background-image: url(static('pretixbase/img/flags/hu.png')); }
pre[lang=id], input[lang=id], textarea[lang=id] { background-image: url(static('pretixbase/img/flags/id.png')); }
pre[lang=ie], input[lang=ie], textarea[lang=ie] { background-image: url(static('pretixbase/img/flags/ie.png')); }
pre[lang=il], input[lang=il], textarea[lang=il] { background-image: url(static('pretixbase/img/flags/il.png')); }
pre[lang=in], input[lang=in], textarea[lang=in] { background-image: url(static('pretixbase/img/flags/in.png')); }
pre[lang=io], input[lang=io], textarea[lang=io] { background-image: url(static('pretixbase/img/flags/io.png')); }
pre[lang=iq], input[lang=iq], textarea[lang=iq] { background-image: url(static('pretixbase/img/flags/iq.png')); }
pre[lang=ir], input[lang=ir], textarea[lang=ir] { background-image: url(static('pretixbase/img/flags/ir.png')); }
pre[lang=is], input[lang=is], textarea[lang=is] { background-image: url(static('pretixbase/img/flags/is.png')); }
pre[lang=it], input[lang=it], textarea[lang=it] { background-image: url(static('pretixbase/img/flags/it.png')); }
pre[lang=jm], input[lang=jm], textarea[lang=jm] { background-image: url(static('pretixbase/img/flags/jm.png')); }
pre[lang=jo], input[lang=jo], textarea[lang=jo] { background-image: url(static('pretixbase/img/flags/jo.png')); }
pre[lang=jp], input[lang=jp], textarea[lang=jp] { background-image: url(static('pretixbase/img/flags/jp.png')); }
pre[lang=ke], input[lang=ke], textarea[lang=ke] { background-image: url(static('pretixbase/img/flags/ke.png')); }
pre[lang=kg], input[lang=kg], textarea[lang=kg] { background-image: url(static('pretixbase/img/flags/kg.png')); }
pre[lang=kh], input[lang=kh], textarea[lang=kh] { background-image: url(static('pretixbase/img/flags/kh.png')); }
pre[lang=ki], input[lang=ki], textarea[lang=ki] { background-image: url(static('pretixbase/img/flags/ki.png')); }
pre[lang=km], input[lang=km], textarea[lang=km] { background-image: url(static('pretixbase/img/flags/km.png')); }
pre[lang=kn], input[lang=kn], textarea[lang=kn] { background-image: url(static('pretixbase/img/flags/kn.png')); }
pre[lang=kp], input[lang=kp], textarea[lang=kp] { background-image: url(static('pretixbase/img/flags/kp.png')); }
pre[lang=kr], input[lang=kr], textarea[lang=kr] { background-image: url(static('pretixbase/img/flags/kr.png')); }
pre[lang=kw], input[lang=kw], textarea[lang=kw] { background-image: url(static('pretixbase/img/flags/kw.png')); }
pre[lang=ky], input[lang=ky], textarea[lang=ky] { background-image: url(static('pretixbase/img/flags/ky.png')); }
pre[lang=kz], input[lang=kz], textarea[lang=kz] { background-image: url(static('pretixbase/img/flags/kz.png')); }
pre[lang=la], input[lang=la], textarea[lang=la] { background-image: url(static('pretixbase/img/flags/la.png')); }
pre[lang=lb], input[lang=lb], textarea[lang=lb] { background-image: url(static('pretixbase/img/flags/lb.png')); }
pre[lang=lc], input[lang=lc], textarea[lang=lc] { background-image: url(static('pretixbase/img/flags/lc.png')); }
pre[lang=li], input[lang=li], textarea[lang=li] { background-image: url(static('pretixbase/img/flags/li.png')); }
pre[lang=lk], input[lang=lk], textarea[lang=lk] { background-image: url(static('pretixbase/img/flags/lk.png')); }
pre[lang=lr], input[lang=lr], textarea[lang=lr] { background-image: url(static('pretixbase/img/flags/lr.png')); }
pre[lang=ls], input[lang=ls], textarea[lang=ls] { background-image: url(static('pretixbase/img/flags/ls.png')); }
pre[lang=lt], input[lang=lt], textarea[lang=lt] { background-image: url(static('pretixbase/img/flags/lt.png')); }
pre[lang=lu], input[lang=lu], textarea[lang=lu] { background-image: url(static('pretixbase/img/flags/lu.png')); }
pre[lang=lv], input[lang=lv], textarea[lang=lv] { background-image: url(static('pretixbase/img/flags/lv.png')); }
pre[lang=ly], input[lang=ly], textarea[lang=ly] { background-image: url(static('pretixbase/img/flags/ly.png')); }
pre[lang=ma], input[lang=ma], textarea[lang=ma] { background-image: url(static('pretixbase/img/flags/ma.png')); }
pre[lang=mc], input[lang=mc], textarea[lang=mc] { background-image: url(static('pretixbase/img/flags/mc.png')); }
pre[lang=md], input[lang=md], textarea[lang=md] { background-image: url(static('pretixbase/img/flags/md.png')); }
pre[lang=me], input[lang=me], textarea[lang=me] { background-image: url(static('pretixbase/img/flags/me.png')); }
pre[lang=mg], input[lang=mg], textarea[lang=mg] { background-image: url(static('pretixbase/img/flags/mg.png')); }
pre[lang=mh], input[lang=mh], textarea[lang=mh] { background-image: url(static('pretixbase/img/flags/mh.png')); }
pre[lang=mk], input[lang=mk], textarea[lang=mk] { background-image: url(static('pretixbase/img/flags/mk.png')); }
pre[lang=ml], input[lang=ml], textarea[lang=ml] { background-image: url(static('pretixbase/img/flags/ml.png')); }
pre[lang=mm], input[lang=mm], textarea[lang=mm] { background-image: url(static('pretixbase/img/flags/mm.png')); }
pre[lang=mn], input[lang=mn], textarea[lang=mn] { background-image: url(static('pretixbase/img/flags/mn.png')); }
pre[lang=mo], input[lang=mo], textarea[lang=mo] { background-image: url(static('pretixbase/img/flags/mo.png')); }
pre[lang=mp], input[lang=mp], textarea[lang=mp] { background-image: url(static('pretixbase/img/flags/mp.png')); }
pre[lang=mq], input[lang=mq], textarea[lang=mq] { background-image: url(static('pretixbase/img/flags/mq.png')); }
pre[lang=mr], input[lang=mr], textarea[lang=mr] { background-image: url(static('pretixbase/img/flags/mr.png')); }
pre[lang=ms], input[lang=ms], textarea[lang=ms] { background-image: url(static('pretixbase/img/flags/ms.png')); }
pre[lang=mt], input[lang=mt], textarea[lang=mt] { background-image: url(static('pretixbase/img/flags/mt.png')); }
pre[lang=mu], input[lang=mu], textarea[lang=mu] { background-image: url(static('pretixbase/img/flags/mu.png')); }
pre[lang=mv], input[lang=mv], textarea[lang=mv] { background-image: url(static('pretixbase/img/flags/mv.png')); }
pre[lang=mw], input[lang=mw], textarea[lang=mw] { background-image: url(static('pretixbase/img/flags/mw.png')); }
pre[lang=mx], input[lang=mx], textarea[lang=mx] { background-image: url(static('pretixbase/img/flags/mx.png')); }
pre[lang=my], input[lang=my], textarea[lang=my] { background-image: url(static('pretixbase/img/flags/my.png')); }
pre[lang=mz], input[lang=mz], textarea[lang=mz] { background-image: url(static('pretixbase/img/flags/mz.png')); }
pre[lang=na], input[lang=na], textarea[lang=na] { background-image: url(static('pretixbase/img/flags/na.png')); }
pre[lang=nc], input[lang=nc], textarea[lang=nc] { background-image: url(static('pretixbase/img/flags/nc.png')); }
pre[lang=ne], input[lang=ne], textarea[lang=ne] { background-image: url(static('pretixbase/img/flags/ne.png')); }
pre[lang=nf], input[lang=nf], textarea[lang=nf] { background-image: url(static('pretixbase/img/flags/nf.png')); }
pre[lang=ng], input[lang=ng], textarea[lang=ng] { background-image: url(static('pretixbase/img/flags/ng.png')); }
pre[lang=ni], input[lang=ni], textarea[lang=ni] { background-image: url(static('pretixbase/img/flags/ni.png')); }
pre[lang=nl], input[lang=nl], textarea[lang=nl] { background-image: url(static('pretixbase/img/flags/nl.png')); }
pre[lang=nl-informal], input[lang=nl-informal], textarea[lang=nl-informal] { background-image: url(static('pretixbase/img/flags/nl.png')); }
pre[lang=no], input[lang=no], textarea[lang=no] { background-image: url(static('pretixbase/img/flags/no.png')); }
pre[lang=np], input[lang=np], textarea[lang=np] { background-image: url(static('pretixbase/img/flags/np.png')); }
pre[lang=nr], input[lang=nr], textarea[lang=nr] { background-image: url(static('pretixbase/img/flags/nr.png')); }
pre[lang=nu], input[lang=nu], textarea[lang=nu] { background-image: url(static('pretixbase/img/flags/nu.png')); }
pre[lang=nz], input[lang=nz], textarea[lang=nz] { background-image: url(static('pretixbase/img/flags/nz.png')); }
pre[lang=om], input[lang=om], textarea[lang=om] { background-image: url(static('pretixbase/img/flags/om.png')); }
pre[lang=pa], input[lang=pa], textarea[lang=pa] { background-image: url(static('pretixbase/img/flags/pa.png')); }
pre[lang=pe], input[lang=pe], textarea[lang=pe] { background-image: url(static('pretixbase/img/flags/pe.png')); }
pre[lang=pf], input[lang=pf], textarea[lang=pf] { background-image: url(static('pretixbase/img/flags/pf.png')); }
pre[lang=pg], input[lang=pg], textarea[lang=pg] { background-image: url(static('pretixbase/img/flags/pg.png')); }
pre[lang=ph], input[lang=ph], textarea[lang=ph] { background-image: url(static('pretixbase/img/flags/ph.png')); }
pre[lang=pk], input[lang=pk], textarea[lang=pk] { background-image: url(static('pretixbase/img/flags/pk.png')); }
pre[lang=pl], input[lang=pl], textarea[lang=pl] { background-image: url(static('pretixbase/img/flags/pl.png')); }
pre[lang=pm], input[lang=pm], textarea[lang=pm] { background-image: url(static('pretixbase/img/flags/pm.png')); }
pre[lang=pn], input[lang=pn], textarea[lang=pn] { background-image: url(static('pretixbase/img/flags/pn.png')); }
pre[lang=pr], input[lang=pr], textarea[lang=pr] { background-image: url(static('pretixbase/img/flags/pr.png')); }
pre[lang=ps], input[lang=ps], textarea[lang=ps] { background-image: url(static('pretixbase/img/flags/ps.png')); }
pre[lang=pt], input[lang=pt], textarea[lang=pt] { background-image: url(static('pretixbase/img/flags/pt.png')); }
pre[lang=pw], input[lang=pw], textarea[lang=pw] { background-image: url(static('pretixbase/img/flags/pw.png')); }
pre[lang=py], input[lang=py], textarea[lang=py] { background-image: url(static('pretixbase/img/flags/py.png')); }
pre[lang=qa], input[lang=qa], textarea[lang=qa] { background-image: url(static('pretixbase/img/flags/qa.png')); }
pre[lang=re], input[lang=re], textarea[lang=re] { background-image: url(static('pretixbase/img/flags/re.png')); }
pre[lang=ro], input[lang=ro], textarea[lang=ro] { background-image: url(static('pretixbase/img/flags/ro.png')); }
pre[lang=rs], input[lang=rs], textarea[lang=rs] { background-image: url(static('pretixbase/img/flags/rs.png')); }
pre[lang=ru], input[lang=ru], textarea[lang=ru] { background-image: url(static('pretixbase/img/flags/ru.png')); }
pre[lang=rw], input[lang=rw], textarea[lang=rw] { background-image: url(static('pretixbase/img/flags/rw.png')); }
pre[lang=sa], input[lang=sa], textarea[lang=sa] { background-image: url(static('pretixbase/img/flags/sa.png')); }
pre[lang=sb], input[lang=sb], textarea[lang=sb] { background-image: url(static('pretixbase/img/flags/sb.png')); }
pre[lang=sc], input[lang=sc], textarea[lang=sc] { background-image: url(static('pretixbase/img/flags/sc.png')); }
pre[lang=sd], input[lang=sd], textarea[lang=sd] { background-image: url(static('pretixbase/img/flags/sd.png')); }
pre[lang=se], input[lang=se], textarea[lang=se] { background-image: url(static('pretixbase/img/flags/se.png')); }
pre[lang=sg], input[lang=sg], textarea[lang=sg] { background-image: url(static('pretixbase/img/flags/sg.png')); }
pre[lang=sh], input[lang=sh], textarea[lang=sh] { background-image: url(static('pretixbase/img/flags/sh.png')); }
pre[lang=si], input[lang=si], textarea[lang=si] { background-image: url(static('pretixbase/img/flags/si.png')); }
pre[lang=sj], input[lang=sj], textarea[lang=sj] { background-image: url(static('pretixbase/img/flags/sj.png')); }
pre[lang=sk], input[lang=sk], textarea[lang=sk] { background-image: url(static('pretixbase/img/flags/sk.png')); }
pre[lang=sl], input[lang=sl], textarea[lang=sl] { background-image: url(static('pretixbase/img/flags/sl.png')); }
pre[lang=sm], input[lang=sm], textarea[lang=sm] { background-image: url(static('pretixbase/img/flags/sm.png')); }
pre[lang=sn], input[lang=sn], textarea[lang=sn] { background-image: url(static('pretixbase/img/flags/sn.png')); }
pre[lang=so], input[lang=so], textarea[lang=so] { background-image: url(static('pretixbase/img/flags/so.png')); }
pre[lang=sr], input[lang=sr], textarea[lang=sr] { background-image: url(static('pretixbase/img/flags/sr.png')); }
pre[lang=st], input[lang=st], textarea[lang=st] { background-image: url(static('pretixbase/img/flags/st.png')); }
pre[lang=sv], input[lang=sv], textarea[lang=sv] { background-image: url(static('pretixbase/img/flags/sv.png')); }
pre[lang=sy], input[lang=sy], textarea[lang=sy] { background-image: url(static('pretixbase/img/flags/sy.png')); }
pre[lang=sz], input[lang=sz], textarea[lang=sz] { background-image: url(static('pretixbase/img/flags/sz.png')); }
pre[lang=tc], input[lang=tc], textarea[lang=tc] { background-image: url(static('pretixbase/img/flags/tc.png')); }
pre[lang=td], input[lang=td], textarea[lang=td] { background-image: url(static('pretixbase/img/flags/td.png')); }
pre[lang=tf], input[lang=tf], textarea[lang=tf] { background-image: url(static('pretixbase/img/flags/tf.png')); }
pre[lang=tg], input[lang=tg], textarea[lang=tg] { background-image: url(static('pretixbase/img/flags/tg.png')); }
pre[lang=th], input[lang=th], textarea[lang=th] { background-image: url(static('pretixbase/img/flags/th.png')); }
pre[lang=tj], input[lang=tj], textarea[lang=tj] { background-image: url(static('pretixbase/img/flags/tj.png')); }
pre[lang=tk], input[lang=tk], textarea[lang=tk] { background-image: url(static('pretixbase/img/flags/tk.png')); }
pre[lang=tl], input[lang=tl], textarea[lang=tl] { background-image: url(static('pretixbase/img/flags/tl.png')); }
pre[lang=tm], input[lang=tm], textarea[lang=tm] { background-image: url(static('pretixbase/img/flags/tm.png')); }
pre[lang=tn], input[lang=tn], textarea[lang=tn] { background-image: url(static('pretixbase/img/flags/tn.png')); }
pre[lang=to], input[lang=to], textarea[lang=to] { background-image: url(static('pretixbase/img/flags/to.png')); }
pre[lang=tr], input[lang=tr], textarea[lang=tr] { background-image: url(static('pretixbase/img/flags/tr.png')); }
pre[lang=tt], input[lang=tt], textarea[lang=tt] { background-image: url(static('pretixbase/img/flags/tt.png')); }
pre[lang=tv], input[lang=tv], textarea[lang=tv] { background-image: url(static('pretixbase/img/flags/tv.png')); }
pre[lang=tw], input[lang=tw], textarea[lang=tw] { background-image: url(static('pretixbase/img/flags/tw.png')); }
pre[lang=tz], input[lang=tz], textarea[lang=tz] { background-image: url(static('pretixbase/img/flags/tz.png')); }
pre[lang=ua], input[lang=ua], textarea[lang=ua] { background-image: url(static('pretixbase/img/flags/ua.png')); }
pre[lang=ug], input[lang=ug], textarea[lang=ug] { background-image: url(static('pretixbase/img/flags/ug.png')); }
pre[lang=um], input[lang=um], textarea[lang=um] { background-image: url(static('pretixbase/img/flags/um.png')); }
pre[lang=us], input[lang=us], textarea[lang=us] { background-image: url(static('pretixbase/img/flags/us.png')); }
pre[lang=uy], input[lang=uy], textarea[lang=uy] { background-image: url(static('pretixbase/img/flags/uy.png')); }
pre[lang=uz], input[lang=uz], textarea[lang=uz] { background-image: url(static('pretixbase/img/flags/uz.png')); }
pre[lang=va], input[lang=va], textarea[lang=va] { background-image: url(static('pretixbase/img/flags/va.png')); }
pre[lang=vc], input[lang=vc], textarea[lang=vc] { background-image: url(static('pretixbase/img/flags/vc.png')); }
pre[lang=ve], input[lang=ve], textarea[lang=ve] { background-image: url(static('pretixbase/img/flags/ve.png')); }
pre[lang=vg], input[lang=vg], textarea[lang=vg] { background-image: url(static('pretixbase/img/flags/vg.png')); }
pre[lang=vi], input[lang=vi], textarea[lang=vi] { background-image: url(static('pretixbase/img/flags/vi.png')); }
pre[lang=vn], input[lang=vn], textarea[lang=vn] { background-image: url(static('pretixbase/img/flags/vn.png')); }
pre[lang=vu], input[lang=vu], textarea[lang=vu] { background-image: url(static('pretixbase/img/flags/vu.png')); }
pre[lang=wf], input[lang=wf], textarea[lang=wf] { background-image: url(static('pretixbase/img/flags/wf.png')); }
pre[lang=ws], input[lang=ws], textarea[lang=ws] { background-image: url(static('pretixbase/img/flags/ws.png')); }
pre[lang=ye], input[lang=ye], textarea[lang=ye] { background-image: url(static('pretixbase/img/flags/ye.png')); }
pre[lang=yt], input[lang=yt], textarea[lang=yt] { background-image: url(static('pretixbase/img/flags/yt.png')); }
pre[lang=za], input[lang=za], textarea[lang=za] { background-image: url(static('pretixbase/img/flags/za.png')); }
pre[lang=zm], input[lang=zm], textarea[lang=zm] { background-image: url(static('pretixbase/img/flags/zm.png')); }
pre[lang=zw], input[lang=zw], textarea[lang=zw] { background-image: url(static('pretixbase/img/flags/zw.png')); }
pre[lang=en], input[lang=en], textarea[lang=en] { background-image: url(static('pretixbase/img/flags/gb.png')); }
pre[lang=ad], input[lang=ad], textarea[lang=ad], div[lang=ad] { background-image: url(static('pretixbase/img/flags/ad.png')); }
pre[lang=ae], input[lang=ae], textarea[lang=ae], div[lang=ae] { background-image: url(static('pretixbase/img/flags/ae.png')); }
pre[lang=af], input[lang=af], textarea[lang=af], div[lang=af] { background-image: url(static('pretixbase/img/flags/af.png')); }
pre[lang=ag], input[lang=ag], textarea[lang=ag], div[lang=ag] { background-image: url(static('pretixbase/img/flags/ag.png')); }
pre[lang=ai], input[lang=ai], textarea[lang=ai], div[lang=ai] { background-image: url(static('pretixbase/img/flags/ai.png')); }
pre[lang=al], input[lang=al], textarea[lang=al], div[lang=al] { background-image: url(static('pretixbase/img/flags/al.png')); }
pre[lang=am], input[lang=am], textarea[lang=am], div[lang=am] { background-image: url(static('pretixbase/img/flags/am.png')); }
pre[lang=an], input[lang=an], textarea[lang=an], div[lang=an] { background-image: url(static('pretixbase/img/flags/an.png')); }
pre[lang=ao], input[lang=ao], textarea[lang=ao], div[lang=ao] { background-image: url(static('pretixbase/img/flags/ao.png')); }
pre[lang=ar], input[lang=ar], textarea[lang=ar], div[lang=ar] { background-image: url(static('pretixbase/img/flags/ar.png')); }
pre[lang=as], input[lang=as], textarea[lang=as], div[lang=as] { background-image: url(static('pretixbase/img/flags/as.png')); }
pre[lang=at], input[lang=at], textarea[lang=at], div[lang=at] { background-image: url(static('pretixbase/img/flags/at.png')); }
pre[lang=au], input[lang=au], textarea[lang=au], div[lang=au] { background-image: url(static('pretixbase/img/flags/au.png')); }
pre[lang=aw], input[lang=aw], textarea[lang=aw], div[lang=aw] { background-image: url(static('pretixbase/img/flags/aw.png')); }
pre[lang=ax], input[lang=ax], textarea[lang=ax], div[lang=ax] { background-image: url(static('pretixbase/img/flags/ax.png')); }
pre[lang=az], input[lang=az], textarea[lang=az], div[lang=az] { background-image: url(static('pretixbase/img/flags/az.png')); }
pre[lang=ba], input[lang=ba], textarea[lang=ba], div[lang=ba] { background-image: url(static('pretixbase/img/flags/ba.png')); }
pre[lang=bb], input[lang=bb], textarea[lang=bb], div[lang=bb] { background-image: url(static('pretixbase/img/flags/bb.png')); }
pre[lang=bd], input[lang=bd], textarea[lang=bd], div[lang=bd] { background-image: url(static('pretixbase/img/flags/bd.png')); }
pre[lang=be], input[lang=be], textarea[lang=be], div[lang=be] { background-image: url(static('pretixbase/img/flags/be.png')); }
pre[lang=bf], input[lang=bf], textarea[lang=bf], div[lang=bf] { background-image: url(static('pretixbase/img/flags/bf.png')); }
pre[lang=bg], input[lang=bg], textarea[lang=bg], div[lang=bg] { background-image: url(static('pretixbase/img/flags/bg.png')); }
pre[lang=bh], input[lang=bh], textarea[lang=bh], div[lang=bh] { background-image: url(static('pretixbase/img/flags/bh.png')); }
pre[lang=bi], input[lang=bi], textarea[lang=bi], div[lang=bi] { background-image: url(static('pretixbase/img/flags/bi.png')); }
pre[lang=bj], input[lang=bj], textarea[lang=bj], div[lang=bj] { background-image: url(static('pretixbase/img/flags/bj.png')); }
pre[lang=bm], input[lang=bm], textarea[lang=bm], div[lang=bm] { background-image: url(static('pretixbase/img/flags/bm.png')); }
pre[lang=bn], input[lang=bn], textarea[lang=bn], div[lang=bn] { background-image: url(static('pretixbase/img/flags/bn.png')); }
pre[lang=bo], input[lang=bo], textarea[lang=bo], div[lang=bo] { background-image: url(static('pretixbase/img/flags/bo.png')); }
pre[lang=br], input[lang=br], textarea[lang=br], div[lang=br] { background-image: url(static('pretixbase/img/flags/br.png')); }
pre[lang=pt-br], input[lang=pt-br], textarea[lang=pt-br], div[lang=pt-br] { background-image: url(static('pretixbase/img/flags/br.png')); }
pre[lang=bs], input[lang=bs], textarea[lang=bs], div[lang=bs] { background-image: url(static('pretixbase/img/flags/bs.png')); }
pre[lang=bt], input[lang=bt], textarea[lang=bt], div[lang=bt] { background-image: url(static('pretixbase/img/flags/bt.png')); }
pre[lang=bv], input[lang=bv], textarea[lang=bv], div[lang=bv] { background-image: url(static('pretixbase/img/flags/bv.png')); }
pre[lang=bw], input[lang=bw], textarea[lang=bw], div[lang=bw] { background-image: url(static('pretixbase/img/flags/bw.png')); }
pre[lang=by], input[lang=by], textarea[lang=by], div[lang=by] { background-image: url(static('pretixbase/img/flags/by.png')); }
pre[lang=bz], input[lang=bz], textarea[lang=bz], div[lang=bz] { background-image: url(static('pretixbase/img/flags/bz.png')); }
pre[lang=ca], input[lang=ca], textarea[lang=ca], div[lang=ca] { background-image: url(static('pretixbase/img/flags/ca.png')); }
pre[lang=cc], input[lang=cc], textarea[lang=cc], div[lang=cc] { background-image: url(static('pretixbase/img/flags/cc.png')); }
pre[lang=cd], input[lang=cd], textarea[lang=cd], div[lang=cd] { background-image: url(static('pretixbase/img/flags/cd.png')); }
pre[lang=cf], input[lang=cf], textarea[lang=cf], div[lang=cf] { background-image: url(static('pretixbase/img/flags/cf.png')); }
pre[lang=cg], input[lang=cg], textarea[lang=cg], div[lang=cg] { background-image: url(static('pretixbase/img/flags/cg.png')); }
pre[lang=ch], input[lang=ch], textarea[lang=ch], div[lang=ch] { background-image: url(static('pretixbase/img/flags/ch.png')); }
pre[lang=ci], input[lang=ci], textarea[lang=ci], div[lang=ci] { background-image: url(static('pretixbase/img/flags/ci.png')); }
pre[lang=ck], input[lang=ck], textarea[lang=ck], div[lang=ck] { background-image: url(static('pretixbase/img/flags/ck.png')); }
pre[lang=cl], input[lang=cl], textarea[lang=cl], div[lang=cl] { background-image: url(static('pretixbase/img/flags/cl.png')); }
pre[lang=cm], input[lang=cm], textarea[lang=cm], div[lang=cm] { background-image: url(static('pretixbase/img/flags/cm.png')); }
pre[lang=cn], input[lang=cn], textarea[lang=cn], div[lang=cn] { background-image: url(static('pretixbase/img/flags/cn.png')); }
pre[lang=co], input[lang=co], textarea[lang=co], div[lang=co] { background-image: url(static('pretixbase/img/flags/co.png')); }
pre[lang=cr], input[lang=cr], textarea[lang=cr], div[lang=cr] { background-image: url(static('pretixbase/img/flags/cr.png')); }
pre[lang=cs], input[lang=cs], textarea[lang=cs], div[lang=cs] { background-image: url(static('pretixbase/img/flags/cs.png')); }
pre[lang=cu], input[lang=cu], textarea[lang=cu], div[lang=cu] { background-image: url(static('pretixbase/img/flags/cu.png')); }
pre[lang=cv], input[lang=cv], textarea[lang=cv], div[lang=cv] { background-image: url(static('pretixbase/img/flags/cv.png')); }
pre[lang=cx], input[lang=cx], textarea[lang=cx], div[lang=cx] { background-image: url(static('pretixbase/img/flags/cx.png')); }
pre[lang=cy], input[lang=cy], textarea[lang=cy], div[lang=cy] { background-image: url(static('pretixbase/img/flags/cy.png')); }
pre[lang=cz], input[lang=cz], textarea[lang=cz], div[lang=cz] { background-image: url(static('pretixbase/img/flags/cz.png')); }
pre[lang=de], input[lang=de], textarea[lang=de], div[lang=de] { background-image: url(static('pretixbase/img/flags/de.png')); }
pre[lang=de-informal], input[lang=de-informal], textarea[lang=de-informal], div[lang=de-informal] { background-image: url(static('pretixbase/img/flags/de-informal.png')); }
pre[lang=dj], input[lang=dj], textarea[lang=dj], div[lang=dj] { background-image: url(static('pretixbase/img/flags/dj.png')); }
pre[lang=da], input[lang=da], textarea[lang=da], div[lang=da] { background-image: url(static('pretixbase/img/flags/dk.png')); }
pre[lang=dk], input[lang=dk], textarea[lang=dk], div[lang=dk] { background-image: url(static('pretixbase/img/flags/dk.png')); }
pre[lang=dm], input[lang=dm], textarea[lang=dm], div[lang=dm] { background-image: url(static('pretixbase/img/flags/dm.png')); }
pre[lang=do], input[lang=do], textarea[lang=do], div[lang=do] { background-image: url(static('pretixbase/img/flags/do.png')); }
pre[lang=dz], input[lang=dz], textarea[lang=dz], div[lang=dz] { background-image: url(static('pretixbase/img/flags/dz.png')); }
pre[lang=ec], input[lang=ec], textarea[lang=ec], div[lang=ec] { background-image: url(static('pretixbase/img/flags/ec.png')); }
pre[lang=ee], input[lang=ee], textarea[lang=ee], div[lang=ee] { background-image: url(static('pretixbase/img/flags/ee.png')); }
pre[lang=eg], input[lang=eg], textarea[lang=eg], div[lang=eg] { background-image: url(static('pretixbase/img/flags/eg.png')); }
pre[lang=eh], input[lang=eh], textarea[lang=eh], div[lang=eh] { background-image: url(static('pretixbase/img/flags/eh.png')); }
pre[lang=er], input[lang=er], textarea[lang=er], div[lang=er] { background-image: url(static('pretixbase/img/flags/er.png')); }
pre[lang=es], input[lang=es], textarea[lang=es], div[lang=es] { background-image: url(static('pretixbase/img/flags/es.png')); }
pre[lang=et], input[lang=et], textarea[lang=et], div[lang=et] { background-image: url(static('pretixbase/img/flags/et.png')); }
pre[lang=fi], input[lang=fi], textarea[lang=fi], div[lang=fi] { background-image: url(static('pretixbase/img/flags/fi.png')); }
pre[lang=fj], input[lang=fj], textarea[lang=fj], div[lang=fj] { background-image: url(static('pretixbase/img/flags/fj.png')); }
pre[lang=fk], input[lang=fk], textarea[lang=fk], div[lang=fk] { background-image: url(static('pretixbase/img/flags/fk.png')); }
pre[lang=fm], input[lang=fm], textarea[lang=fm], div[lang=fm] { background-image: url(static('pretixbase/img/flags/fm.png')); }
pre[lang=fo], input[lang=fo], textarea[lang=fo], div[lang=fo] { background-image: url(static('pretixbase/img/flags/fo.png')); }
pre[lang=fr], input[lang=fr], textarea[lang=fr], div[lang=fr] { background-image: url(static('pretixbase/img/flags/fr.png')); }
pre[lang=ga], input[lang=ga], textarea[lang=ga], div[lang=ga] { background-image: url(static('pretixbase/img/flags/ga.png')); }
pre[lang=gb], input[lang=gb], textarea[lang=gb], div[lang=gb] { background-image: url(static('pretixbase/img/flags/gb.png')); }
pre[lang=gd], input[lang=gd], textarea[lang=gd], div[lang=gd] { background-image: url(static('pretixbase/img/flags/gd.png')); }
pre[lang=ge], input[lang=ge], textarea[lang=ge], div[lang=ge] { background-image: url(static('pretixbase/img/flags/ge.png')); }
pre[lang=gf], input[lang=gf], textarea[lang=gf], div[lang=gf] { background-image: url(static('pretixbase/img/flags/gf.png')); }
pre[lang=gh], input[lang=gh], textarea[lang=gh], div[lang=gh] { background-image: url(static('pretixbase/img/flags/gh.png')); }
pre[lang=gi], input[lang=gi], textarea[lang=gi], div[lang=gi] { background-image: url(static('pretixbase/img/flags/gi.png')); }
pre[lang=gl], input[lang=gl], textarea[lang=gl], div[lang=gl] { background-image: url(static('pretixbase/img/flags/gl.png')); }
pre[lang=gm], input[lang=gm], textarea[lang=gm], div[lang=gm] { background-image: url(static('pretixbase/img/flags/gm.png')); }
pre[lang=gn], input[lang=gn], textarea[lang=gn], div[lang=gn] { background-image: url(static('pretixbase/img/flags/gn.png')); }
pre[lang=gp], input[lang=gp], textarea[lang=gp], div[lang=gp] { background-image: url(static('pretixbase/img/flags/gp.png')); }
pre[lang=gq], input[lang=gq], textarea[lang=gq], div[lang=gq] { background-image: url(static('pretixbase/img/flags/gq.png')); }
pre[lang=gr], input[lang=gr], textarea[lang=gr], div[lang=gr] { background-image: url(static('pretixbase/img/flags/gr.png')); }
pre[lang=gs], input[lang=gs], textarea[lang=gs], div[lang=gs] { background-image: url(static('pretixbase/img/flags/gs.png')); }
pre[lang=gt], input[lang=gt], textarea[lang=gt], div[lang=gt] { background-image: url(static('pretixbase/img/flags/gt.png')); }
pre[lang=gu], input[lang=gu], textarea[lang=gu], div[lang=gu] { background-image: url(static('pretixbase/img/flags/gu.png')); }
pre[lang=gw], input[lang=gw], textarea[lang=gw], div[lang=gw] { background-image: url(static('pretixbase/img/flags/gw.png')); }
pre[lang=gy], input[lang=gy], textarea[lang=gy], div[lang=gy] { background-image: url(static('pretixbase/img/flags/gy.png')); }
pre[lang=hk], input[lang=hk], textarea[lang=hk], div[lang=hk] { background-image: url(static('pretixbase/img/flags/hk.png')); }
pre[lang=hm], input[lang=hm], textarea[lang=hm], div[lang=hm] { background-image: url(static('pretixbase/img/flags/hm.png')); }
pre[lang=hn], input[lang=hn], textarea[lang=hn], div[lang=hn] { background-image: url(static('pretixbase/img/flags/hn.png')); }
pre[lang=hr], input[lang=hr], textarea[lang=hr], div[lang=hr] { background-image: url(static('pretixbase/img/flags/hr.png')); }
pre[lang=ht], input[lang=ht], textarea[lang=ht], div[lang=ht] { background-image: url(static('pretixbase/img/flags/ht.png')); }
pre[lang=hu], input[lang=hu], textarea[lang=hu], div[lang=hu] { background-image: url(static('pretixbase/img/flags/hu.png')); }
pre[lang=id], input[lang=id], textarea[lang=id], div[lang=id] { background-image: url(static('pretixbase/img/flags/id.png')); }
pre[lang=ie], input[lang=ie], textarea[lang=ie], div[lang=ie] { background-image: url(static('pretixbase/img/flags/ie.png')); }
pre[lang=il], input[lang=il], textarea[lang=il], div[lang=il] { background-image: url(static('pretixbase/img/flags/il.png')); }
pre[lang=in], input[lang=in], textarea[lang=in], div[lang=in] { background-image: url(static('pretixbase/img/flags/in.png')); }
pre[lang=io], input[lang=io], textarea[lang=io], div[lang=io] { background-image: url(static('pretixbase/img/flags/io.png')); }
pre[lang=iq], input[lang=iq], textarea[lang=iq], div[lang=iq] { background-image: url(static('pretixbase/img/flags/iq.png')); }
pre[lang=ir], input[lang=ir], textarea[lang=ir], div[lang=ir] { background-image: url(static('pretixbase/img/flags/ir.png')); }
pre[lang=is], input[lang=is], textarea[lang=is], div[lang=is] { background-image: url(static('pretixbase/img/flags/is.png')); }
pre[lang=it], input[lang=it], textarea[lang=it], div[lang=it] { background-image: url(static('pretixbase/img/flags/it.png')); }
pre[lang=jm], input[lang=jm], textarea[lang=jm], div[lang=jm] { background-image: url(static('pretixbase/img/flags/jm.png')); }
pre[lang=jo], input[lang=jo], textarea[lang=jo], div[lang=jo] { background-image: url(static('pretixbase/img/flags/jo.png')); }
pre[lang=jp], input[lang=jp], textarea[lang=jp], div[lang=jp] { background-image: url(static('pretixbase/img/flags/jp.png')); }
pre[lang=ke], input[lang=ke], textarea[lang=ke], div[lang=ke] { background-image: url(static('pretixbase/img/flags/ke.png')); }
pre[lang=kg], input[lang=kg], textarea[lang=kg], div[lang=kg] { background-image: url(static('pretixbase/img/flags/kg.png')); }
pre[lang=kh], input[lang=kh], textarea[lang=kh], div[lang=kh] { background-image: url(static('pretixbase/img/flags/kh.png')); }
pre[lang=ki], input[lang=ki], textarea[lang=ki], div[lang=ki] { background-image: url(static('pretixbase/img/flags/ki.png')); }
pre[lang=km], input[lang=km], textarea[lang=km], div[lang=km] { background-image: url(static('pretixbase/img/flags/km.png')); }
pre[lang=kn], input[lang=kn], textarea[lang=kn], div[lang=kn] { background-image: url(static('pretixbase/img/flags/kn.png')); }
pre[lang=kp], input[lang=kp], textarea[lang=kp], div[lang=kp] { background-image: url(static('pretixbase/img/flags/kp.png')); }
pre[lang=kr], input[lang=kr], textarea[lang=kr], div[lang=kr] { background-image: url(static('pretixbase/img/flags/kr.png')); }
pre[lang=kw], input[lang=kw], textarea[lang=kw], div[lang=kw] { background-image: url(static('pretixbase/img/flags/kw.png')); }
pre[lang=ky], input[lang=ky], textarea[lang=ky], div[lang=ky] { background-image: url(static('pretixbase/img/flags/ky.png')); }
pre[lang=kz], input[lang=kz], textarea[lang=kz], div[lang=kz] { background-image: url(static('pretixbase/img/flags/kz.png')); }
pre[lang=la], input[lang=la], textarea[lang=la], div[lang=la] { background-image: url(static('pretixbase/img/flags/la.png')); }
pre[lang=lb], input[lang=lb], textarea[lang=lb], div[lang=lb] { background-image: url(static('pretixbase/img/flags/lb.png')); }
pre[lang=lc], input[lang=lc], textarea[lang=lc], div[lang=lc] { background-image: url(static('pretixbase/img/flags/lc.png')); }
pre[lang=li], input[lang=li], textarea[lang=li], div[lang=li] { background-image: url(static('pretixbase/img/flags/li.png')); }
pre[lang=lk], input[lang=lk], textarea[lang=lk], div[lang=lk] { background-image: url(static('pretixbase/img/flags/lk.png')); }
pre[lang=lr], input[lang=lr], textarea[lang=lr], div[lang=lr] { background-image: url(static('pretixbase/img/flags/lr.png')); }
pre[lang=ls], input[lang=ls], textarea[lang=ls], div[lang=ls] { background-image: url(static('pretixbase/img/flags/ls.png')); }
pre[lang=lt], input[lang=lt], textarea[lang=lt], div[lang=lt] { background-image: url(static('pretixbase/img/flags/lt.png')); }
pre[lang=lu], input[lang=lu], textarea[lang=lu], div[lang=lu] { background-image: url(static('pretixbase/img/flags/lu.png')); }
pre[lang=lv], input[lang=lv], textarea[lang=lv], div[lang=lv] { background-image: url(static('pretixbase/img/flags/lv.png')); }
pre[lang=ly], input[lang=ly], textarea[lang=ly], div[lang=ly] { background-image: url(static('pretixbase/img/flags/ly.png')); }
pre[lang=ma], input[lang=ma], textarea[lang=ma], div[lang=ma] { background-image: url(static('pretixbase/img/flags/ma.png')); }
pre[lang=mc], input[lang=mc], textarea[lang=mc], div[lang=mc] { background-image: url(static('pretixbase/img/flags/mc.png')); }
pre[lang=md], input[lang=md], textarea[lang=md], div[lang=md] { background-image: url(static('pretixbase/img/flags/md.png')); }
pre[lang=me], input[lang=me], textarea[lang=me], div[lang=me] { background-image: url(static('pretixbase/img/flags/me.png')); }
pre[lang=mg], input[lang=mg], textarea[lang=mg], div[lang=mg] { background-image: url(static('pretixbase/img/flags/mg.png')); }
pre[lang=mh], input[lang=mh], textarea[lang=mh], div[lang=mh] { background-image: url(static('pretixbase/img/flags/mh.png')); }
pre[lang=mk], input[lang=mk], textarea[lang=mk], div[lang=mk] { background-image: url(static('pretixbase/img/flags/mk.png')); }
pre[lang=ml], input[lang=ml], textarea[lang=ml], div[lang=ml] { background-image: url(static('pretixbase/img/flags/ml.png')); }
pre[lang=mm], input[lang=mm], textarea[lang=mm], div[lang=mm] { background-image: url(static('pretixbase/img/flags/mm.png')); }
pre[lang=mn], input[lang=mn], textarea[lang=mn], div[lang=mn] { background-image: url(static('pretixbase/img/flags/mn.png')); }
pre[lang=mo], input[lang=mo], textarea[lang=mo], div[lang=mo] { background-image: url(static('pretixbase/img/flags/mo.png')); }
pre[lang=mp], input[lang=mp], textarea[lang=mp], div[lang=mp] { background-image: url(static('pretixbase/img/flags/mp.png')); }
pre[lang=mq], input[lang=mq], textarea[lang=mq], div[lang=mq] { background-image: url(static('pretixbase/img/flags/mq.png')); }
pre[lang=mr], input[lang=mr], textarea[lang=mr], div[lang=mr] { background-image: url(static('pretixbase/img/flags/mr.png')); }
pre[lang=ms], input[lang=ms], textarea[lang=ms], div[lang=ms] { background-image: url(static('pretixbase/img/flags/ms.png')); }
pre[lang=mt], input[lang=mt], textarea[lang=mt], div[lang=mt] { background-image: url(static('pretixbase/img/flags/mt.png')); }
pre[lang=mu], input[lang=mu], textarea[lang=mu], div[lang=mu] { background-image: url(static('pretixbase/img/flags/mu.png')); }
pre[lang=mv], input[lang=mv], textarea[lang=mv], div[lang=mv] { background-image: url(static('pretixbase/img/flags/mv.png')); }
pre[lang=mw], input[lang=mw], textarea[lang=mw], div[lang=mw] { background-image: url(static('pretixbase/img/flags/mw.png')); }
pre[lang=mx], input[lang=mx], textarea[lang=mx], div[lang=mx] { background-image: url(static('pretixbase/img/flags/mx.png')); }
pre[lang=my], input[lang=my], textarea[lang=my], div[lang=my] { background-image: url(static('pretixbase/img/flags/my.png')); }
pre[lang=mz], input[lang=mz], textarea[lang=mz], div[lang=mz] { background-image: url(static('pretixbase/img/flags/mz.png')); }
pre[lang=na], input[lang=na], textarea[lang=na], div[lang=na] { background-image: url(static('pretixbase/img/flags/na.png')); }
pre[lang=nc], input[lang=nc], textarea[lang=nc], div[lang=nc] { background-image: url(static('pretixbase/img/flags/nc.png')); }
pre[lang=ne], input[lang=ne], textarea[lang=ne], div[lang=ne] { background-image: url(static('pretixbase/img/flags/ne.png')); }
pre[lang=nf], input[lang=nf], textarea[lang=nf], div[lang=nf] { background-image: url(static('pretixbase/img/flags/nf.png')); }
pre[lang=ng], input[lang=ng], textarea[lang=ng], div[lang=ng] { background-image: url(static('pretixbase/img/flags/ng.png')); }
pre[lang=ni], input[lang=ni], textarea[lang=ni], div[lang=ni] { background-image: url(static('pretixbase/img/flags/ni.png')); }
pre[lang=nl], input[lang=nl], textarea[lang=nl], div[lang=nl] { background-image: url(static('pretixbase/img/flags/nl.png')); }
pre[lang=nl-informal], input[lang=nl-informal], textarea[lang=nl-informal], div[lang=nl-informal] { background-image: url(static('pretixbase/img/flags/nl.png')); }
pre[lang=no], input[lang=no], textarea[lang=no], div[lang=no] { background-image: url(static('pretixbase/img/flags/no.png')); }
pre[lang=np], input[lang=np], textarea[lang=np], div[lang=np] { background-image: url(static('pretixbase/img/flags/np.png')); }
pre[lang=nr], input[lang=nr], textarea[lang=nr], div[lang=nr] { background-image: url(static('pretixbase/img/flags/nr.png')); }
pre[lang=nu], input[lang=nu], textarea[lang=nu], div[lang=nu] { background-image: url(static('pretixbase/img/flags/nu.png')); }
pre[lang=nz], input[lang=nz], textarea[lang=nz], div[lang=nz] { background-image: url(static('pretixbase/img/flags/nz.png')); }
pre[lang=om], input[lang=om], textarea[lang=om], div[lang=om] { background-image: url(static('pretixbase/img/flags/om.png')); }
pre[lang=pa], input[lang=pa], textarea[lang=pa], div[lang=pa] { background-image: url(static('pretixbase/img/flags/pa.png')); }
pre[lang=pe], input[lang=pe], textarea[lang=pe], div[lang=pe] { background-image: url(static('pretixbase/img/flags/pe.png')); }
pre[lang=pf], input[lang=pf], textarea[lang=pf], div[lang=pf] { background-image: url(static('pretixbase/img/flags/pf.png')); }
pre[lang=pg], input[lang=pg], textarea[lang=pg], div[lang=pg] { background-image: url(static('pretixbase/img/flags/pg.png')); }
pre[lang=ph], input[lang=ph], textarea[lang=ph], div[lang=ph] { background-image: url(static('pretixbase/img/flags/ph.png')); }
pre[lang=pk], input[lang=pk], textarea[lang=pk], div[lang=pk] { background-image: url(static('pretixbase/img/flags/pk.png')); }
pre[lang=pl], input[lang=pl], textarea[lang=pl], div[lang=pl] { background-image: url(static('pretixbase/img/flags/pl.png')); }
pre[lang=pm], input[lang=pm], textarea[lang=pm], div[lang=pm] { background-image: url(static('pretixbase/img/flags/pm.png')); }
pre[lang=pn], input[lang=pn], textarea[lang=pn], div[lang=pn] { background-image: url(static('pretixbase/img/flags/pn.png')); }
pre[lang=pr], input[lang=pr], textarea[lang=pr], div[lang=pr] { background-image: url(static('pretixbase/img/flags/pr.png')); }
pre[lang=ps], input[lang=ps], textarea[lang=ps], div[lang=ps] { background-image: url(static('pretixbase/img/flags/ps.png')); }
pre[lang=pt], input[lang=pt], textarea[lang=pt], div[lang=pt] { background-image: url(static('pretixbase/img/flags/pt.png')); }
pre[lang=pw], input[lang=pw], textarea[lang=pw], div[lang=pw] { background-image: url(static('pretixbase/img/flags/pw.png')); }
pre[lang=py], input[lang=py], textarea[lang=py], div[lang=py] { background-image: url(static('pretixbase/img/flags/py.png')); }
pre[lang=qa], input[lang=qa], textarea[lang=qa], div[lang=qa] { background-image: url(static('pretixbase/img/flags/qa.png')); }
pre[lang=re], input[lang=re], textarea[lang=re], div[lang=re] { background-image: url(static('pretixbase/img/flags/re.png')); }
pre[lang=ro], input[lang=ro], textarea[lang=ro], div[lang=ro] { background-image: url(static('pretixbase/img/flags/ro.png')); }
pre[lang=rs], input[lang=rs], textarea[lang=rs], div[lang=rs] { background-image: url(static('pretixbase/img/flags/rs.png')); }
pre[lang=ru], input[lang=ru], textarea[lang=ru], div[lang=ru] { background-image: url(static('pretixbase/img/flags/ru.png')); }
pre[lang=rw], input[lang=rw], textarea[lang=rw], div[lang=rw] { background-image: url(static('pretixbase/img/flags/rw.png')); }
pre[lang=sa], input[lang=sa], textarea[lang=sa], div[lang=sa] { background-image: url(static('pretixbase/img/flags/sa.png')); }
pre[lang=sb], input[lang=sb], textarea[lang=sb], div[lang=sb] { background-image: url(static('pretixbase/img/flags/sb.png')); }
pre[lang=sc], input[lang=sc], textarea[lang=sc], div[lang=sc] { background-image: url(static('pretixbase/img/flags/sc.png')); }
pre[lang=sd], input[lang=sd], textarea[lang=sd], div[lang=sd] { background-image: url(static('pretixbase/img/flags/sd.png')); }
pre[lang=se], input[lang=se], textarea[lang=se], div[lang=se] { background-image: url(static('pretixbase/img/flags/se.png')); }
pre[lang=sg], input[lang=sg], textarea[lang=sg], div[lang=sg] { background-image: url(static('pretixbase/img/flags/sg.png')); }
pre[lang=sh], input[lang=sh], textarea[lang=sh], div[lang=sh] { background-image: url(static('pretixbase/img/flags/sh.png')); }
pre[lang=si], input[lang=si], textarea[lang=si], div[lang=si] { background-image: url(static('pretixbase/img/flags/si.png')); }
pre[lang=sj], input[lang=sj], textarea[lang=sj], div[lang=sj] { background-image: url(static('pretixbase/img/flags/sj.png')); }
pre[lang=sk], input[lang=sk], textarea[lang=sk], div[lang=sk] { background-image: url(static('pretixbase/img/flags/sk.png')); }
pre[lang=sl], input[lang=sl], textarea[lang=sl], div[lang=sl] { background-image: url(static('pretixbase/img/flags/sl.png')); }
pre[lang=sm], input[lang=sm], textarea[lang=sm], div[lang=sm] { background-image: url(static('pretixbase/img/flags/sm.png')); }
pre[lang=sn], input[lang=sn], textarea[lang=sn], div[lang=sn] { background-image: url(static('pretixbase/img/flags/sn.png')); }
pre[lang=so], input[lang=so], textarea[lang=so], div[lang=so] { background-image: url(static('pretixbase/img/flags/so.png')); }
pre[lang=sr], input[lang=sr], textarea[lang=sr], div[lang=sr] { background-image: url(static('pretixbase/img/flags/sr.png')); }
pre[lang=st], input[lang=st], textarea[lang=st], div[lang=st] { background-image: url(static('pretixbase/img/flags/st.png')); }
pre[lang=sv], input[lang=sv], textarea[lang=sv], div[lang=sv] { background-image: url(static('pretixbase/img/flags/sv.png')); }
pre[lang=sy], input[lang=sy], textarea[lang=sy], div[lang=sy] { background-image: url(static('pretixbase/img/flags/sy.png')); }
pre[lang=sz], input[lang=sz], textarea[lang=sz], div[lang=sz] { background-image: url(static('pretixbase/img/flags/sz.png')); }
pre[lang=tc], input[lang=tc], textarea[lang=tc], div[lang=tc] { background-image: url(static('pretixbase/img/flags/tc.png')); }
pre[lang=td], input[lang=td], textarea[lang=td], div[lang=td] { background-image: url(static('pretixbase/img/flags/td.png')); }
pre[lang=tf], input[lang=tf], textarea[lang=tf], div[lang=tf] { background-image: url(static('pretixbase/img/flags/tf.png')); }
pre[lang=tg], input[lang=tg], textarea[lang=tg], div[lang=tg] { background-image: url(static('pretixbase/img/flags/tg.png')); }
pre[lang=th], input[lang=th], textarea[lang=th], div[lang=th] { background-image: url(static('pretixbase/img/flags/th.png')); }
pre[lang=tj], input[lang=tj], textarea[lang=tj], div[lang=tj] { background-image: url(static('pretixbase/img/flags/tj.png')); }
pre[lang=tk], input[lang=tk], textarea[lang=tk], div[lang=tk] { background-image: url(static('pretixbase/img/flags/tk.png')); }
pre[lang=tl], input[lang=tl], textarea[lang=tl], div[lang=tl] { background-image: url(static('pretixbase/img/flags/tl.png')); }
pre[lang=tm], input[lang=tm], textarea[lang=tm], div[lang=tm] { background-image: url(static('pretixbase/img/flags/tm.png')); }
pre[lang=tn], input[lang=tn], textarea[lang=tn], div[lang=tn] { background-image: url(static('pretixbase/img/flags/tn.png')); }
pre[lang=to], input[lang=to], textarea[lang=to], div[lang=to] { background-image: url(static('pretixbase/img/flags/to.png')); }
pre[lang=tr], input[lang=tr], textarea[lang=tr], div[lang=tr] { background-image: url(static('pretixbase/img/flags/tr.png')); }
pre[lang=tt], input[lang=tt], textarea[lang=tt], div[lang=tt] { background-image: url(static('pretixbase/img/flags/tt.png')); }
pre[lang=tv], input[lang=tv], textarea[lang=tv], div[lang=tv] { background-image: url(static('pretixbase/img/flags/tv.png')); }
pre[lang=tw], input[lang=tw], textarea[lang=tw], div[lang=tw] { background-image: url(static('pretixbase/img/flags/tw.png')); }
pre[lang=tz], input[lang=tz], textarea[lang=tz], div[lang=tz] { background-image: url(static('pretixbase/img/flags/tz.png')); }
pre[lang=ua], input[lang=ua], textarea[lang=ua], div[lang=ua] { background-image: url(static('pretixbase/img/flags/ua.png')); }
pre[lang=ug], input[lang=ug], textarea[lang=ug], div[lang=ug] { background-image: url(static('pretixbase/img/flags/ug.png')); }
pre[lang=um], input[lang=um], textarea[lang=um], div[lang=um] { background-image: url(static('pretixbase/img/flags/um.png')); }
pre[lang=us], input[lang=us], textarea[lang=us], div[lang=us] { background-image: url(static('pretixbase/img/flags/us.png')); }
pre[lang=uy], input[lang=uy], textarea[lang=uy], div[lang=uy] { background-image: url(static('pretixbase/img/flags/uy.png')); }
pre[lang=uz], input[lang=uz], textarea[lang=uz], div[lang=uz] { background-image: url(static('pretixbase/img/flags/uz.png')); }
pre[lang=va], input[lang=va], textarea[lang=va], div[lang=va] { background-image: url(static('pretixbase/img/flags/va.png')); }
pre[lang=vc], input[lang=vc], textarea[lang=vc], div[lang=vc] { background-image: url(static('pretixbase/img/flags/vc.png')); }
pre[lang=ve], input[lang=ve], textarea[lang=ve], div[lang=ve] { background-image: url(static('pretixbase/img/flags/ve.png')); }
pre[lang=vg], input[lang=vg], textarea[lang=vg], div[lang=vg] { background-image: url(static('pretixbase/img/flags/vg.png')); }
pre[lang=vi], input[lang=vi], textarea[lang=vi], div[lang=vi] { background-image: url(static('pretixbase/img/flags/vi.png')); }
pre[lang=vn], input[lang=vn], textarea[lang=vn], div[lang=vn] { background-image: url(static('pretixbase/img/flags/vn.png')); }
pre[lang=vu], input[lang=vu], textarea[lang=vu], div[lang=vu] { background-image: url(static('pretixbase/img/flags/vu.png')); }
pre[lang=wf], input[lang=wf], textarea[lang=wf], div[lang=wf] { background-image: url(static('pretixbase/img/flags/wf.png')); }
pre[lang=ws], input[lang=ws], textarea[lang=ws], div[lang=ws] { background-image: url(static('pretixbase/img/flags/ws.png')); }
pre[lang=ye], input[lang=ye], textarea[lang=ye], div[lang=ye] { background-image: url(static('pretixbase/img/flags/ye.png')); }
pre[lang=yt], input[lang=yt], textarea[lang=yt], div[lang=yt] { background-image: url(static('pretixbase/img/flags/yt.png')); }
pre[lang=za], input[lang=za], textarea[lang=za], div[lang=za] { background-image: url(static('pretixbase/img/flags/za.png')); }
pre[lang=zm], input[lang=zm], textarea[lang=zm], div[lang=zm] { background-image: url(static('pretixbase/img/flags/zm.png')); }
pre[lang=zw], input[lang=zw], textarea[lang=zw], div[lang=zw] { background-image: url(static('pretixbase/img/flags/zw.png')); }
pre[lang=en], input[lang=en], textarea[lang=en], div[lang=en] { background-image: url(static('pretixbase/img/flags/gb.png')); }

View File

@@ -144,7 +144,8 @@ div.mail-preview {
@include border-bottom-radius(0px);
border-top-width: 0;
margin-bottom: 0;
padding: 15px;
padding-right: 15px;
padding-bottom: 15px;
&:first-child {
@include border-top-radius($input-border-radius);

View File

@@ -616,6 +616,7 @@ class OrderTestCase(BaseQuotaTestCase):
).confirm()
self.order = Order.objects.get(id=self.order.id)
self.assertEqual(self.order.status, Order.STATUS_PAID)
assert not self.order.all_logentries().filter(action_type='pretix.event.order.overpaid').exists()
def test_paid_expired_available(self):
self.event.settings.payment_term_last = (now() + timedelta(days=2)).strftime('%Y-%m-%d')
@@ -742,6 +743,16 @@ class OrderTestCase(BaseQuotaTestCase):
self.order = Order.objects.get(id=self.order.id)
self.assertEqual(self.order.status, Order.STATUS_PAID)
def test_paid_overpaid(self):
self.quota.size = 2
self.quota.save()
self.order.payments.create(
provider='manual', amount=self.order.total + 2
).confirm(count_waitinglist=False)
self.order = Order.objects.get(id=self.order.id)
self.assertEqual(self.order.status, Order.STATUS_PAID)
assert self.order.all_logentries().filter(action_type='pretix.event.order.overpaid').exists()
def test_can_modify_answers(self):
self.event.settings.set('invoice_address_asked', False)
self.event.settings.set('attendee_names_asked', True)

View File

@@ -46,6 +46,11 @@ def test_api_list(env, client):
env[0].slug, env[0].organizer.slug)).content.decode('utf-8')
)
assert r['results'] == [res]
r = json.loads(
client.get('/api/v1/organizers/{}/events/{}/badgeitems/'.format(
env[0].slug, env[0].organizer.slug)).content.decode('utf-8')
)
assert r['results'] == [{'item': env[3].pk, 'layout': env[2].pk, 'id': env[2].item_assignments.first().pk}]
@pytest.mark.django_db

View File

@@ -76,6 +76,7 @@ def test_sendmail_simple_case(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.'
},
@@ -100,6 +101,7 @@ def test_sendmail_email_not_sent_if_order_not_match(logged_in_client, sendmail_u
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'p',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.'
},
@@ -114,6 +116,7 @@ def test_sendmail_preview(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
'action': 'preview'
@@ -130,6 +133,7 @@ def test_sendmail_invalid_data(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
},
follow=True)
@@ -154,6 +158,7 @@ def test_sendmail_multi_locales(logged_in_client, sendmail_url, event, item):
response = logged_in_client.post(sendmail_url,
{'sendto': 'p',
'items': item.pk,
'subject_0': 'Test subject',
'message_0': 'Test message',
'subject_1': 'Benutzer',
@@ -189,6 +194,7 @@ def test_sendmail_subevents(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
'subevent': se1.pk
@@ -201,6 +207,7 @@ def test_sendmail_subevents(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
'subevent': se2.pk
@@ -220,6 +227,7 @@ def test_sendmail_placeholder(logged_in_client, sendmail_url, event, order):
djmail.outbox = []
response = logged_in_client.post(sendmail_url,
{'sendto': 'n',
'items': order.positions.first().item_id,
'subject_0': '{code} Test subject',
'message_0': 'This is a test file for sending mails.',
'action': 'preview'

View File

@@ -46,6 +46,12 @@ def test_api_list(env, client):
env[0].slug, env[0].organizer.slug)).content.decode('utf-8')
)
assert r['results'] == [res]
r = json.loads(
client.get('/api/v1/organizers/{}/events/{}/ticketlayoutitems/'.format(
env[0].slug, env[0].organizer.slug)).content.decode('utf-8')
)
assert r['results'] == [{'item': env[3].pk, 'layout': env[2].pk, 'id': env[2].item_assignments.first().pk,
'sales_channel': 'web'}]
@pytest.mark.django_db