mirror of
https://github.com/pretix/pretix.git
synced 2026-01-12 22:42:26 +00:00
Compare commits
1 Commits
v1.4.0
...
custom-man
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db67959abf |
@@ -51,7 +51,7 @@ If there is a problem, a status code in the ``5xx`` range will be returned.
|
||||
Performance monitoring
|
||||
----------------------
|
||||
|
||||
If you want to generate detailed performance statistics of your pretix installation, there is an
|
||||
If you to generate detailled performance statistics of your pretix installation, there is an
|
||||
endpoint at ``https://pretix.mydomain.com/metrics`` (no slash at the end) which returns a
|
||||
number of values in the text format understood by monitoring tools like Prometheus_. This data
|
||||
is only collected and exposed if you enable it in the :ref:`metrics-settings` section of your
|
||||
|
||||
@@ -25,7 +25,7 @@ Frontend
|
||||
--------
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, contact_form_fields, checkout_confirm_messages
|
||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, checkout_confirm_messages
|
||||
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
|
||||
@@ -40,7 +40,7 @@ automatically). If you are working on Ubuntu or Debian, we strongly recommend up
|
||||
your pip and setuptools installation inside the virtual environment, otherwise some of
|
||||
the dependencies might fail::
|
||||
|
||||
pip3 install -U pip setuptools
|
||||
pip3 install -U pip setuptools==28.6.1
|
||||
|
||||
Working with the code
|
||||
---------------------
|
||||
@@ -81,7 +81,7 @@ and head to http://localhost:8000/
|
||||
|
||||
As we did not implement an overall front page yet, you need to go directly to
|
||||
http://localhost:8000/control/ for the admin view or, if you imported the test
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2018/
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2017/
|
||||
|
||||
.. note:: If you want the development server to listen on a different interface or
|
||||
port (for example because you develop on `pretixdroid`_), you can check
|
||||
|
||||
@@ -15,8 +15,7 @@ ways that pretix itself is:
|
||||
* PDF ticket output
|
||||
|
||||
The following plugins are not shipped with pretix but are maintained by the
|
||||
same team. We update them regularly to make them compatible with the latest
|
||||
pretix releases:
|
||||
same team:
|
||||
|
||||
* `SEPA direct debit`_
|
||||
* `Pages`_
|
||||
@@ -24,17 +23,8 @@ pretix releases:
|
||||
* `Cartshare`_
|
||||
* `Fontpack Free fonts`_
|
||||
|
||||
The following closed-source plugins are available to customers of the hosted pretix.eu platform.
|
||||
Please get in touch with the pretix team if you want to have them for your self-hosted
|
||||
pretix installation:
|
||||
|
||||
* Campaign tracking
|
||||
* Integration with Google Analytics and Facebook Pixel
|
||||
* Integration with Slack
|
||||
* Integration with MailChimp
|
||||
|
||||
The following plugins are from independent third-party authors, so we can make
|
||||
no statements about their stability or compatibility:
|
||||
no statements about their stability:
|
||||
|
||||
* `esPass ticket output`_
|
||||
* `IcePay integration`_
|
||||
|
||||
@@ -36,11 +36,11 @@ t = Team.objects.get_or_create(
|
||||
can_change_organizer_settings=True, can_change_event_settings=True, can_change_items=True,
|
||||
can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True
|
||||
)
|
||||
t[0].members.add(user)
|
||||
cat_tickets = ItemCategory.objects.create(
|
||||
t.members.add(user)
|
||||
cat_tickets = ItemCategory.all.create(
|
||||
event=event, name='Tickets'
|
||||
)
|
||||
cat_merch = ItemCategory.objects.create(
|
||||
cat_merch = ItemCategory.all.create(
|
||||
event=event, name='Merchandise'
|
||||
)
|
||||
question = Question.objects.create(
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "1.4.0"
|
||||
__version__ = "1.4.0-dev0"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.7 on 2017-05-21 09:42
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def rename_placeholder(app, schema_editor):
|
||||
EventSettingsStore = app.get_model('pretixbase', 'Event_SettingsStore')
|
||||
|
||||
for setting in EventSettingsStore.objects.all():
|
||||
if setting.key == 'mail_text_order_placed':
|
||||
new_value = setting.value.replace('{paymentinfo}', '{payment_info}')
|
||||
setting.value = new_value
|
||||
cache.delete('hierarkey_{}_{}'.format('event', setting.object_id))
|
||||
setting.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0060_auto_20170510_1027'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_placeholder, migrations.RunPython.noop)
|
||||
]
|
||||
@@ -2,6 +2,7 @@ import json
|
||||
import uuid
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core import checks
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_delete
|
||||
from django.dispatch import receiver
|
||||
@@ -34,7 +35,6 @@ def cached_file_delete(sender, instance, **kwargs):
|
||||
|
||||
|
||||
class LoggingMixin:
|
||||
|
||||
def log_action(self, action, data=None, user=None):
|
||||
"""
|
||||
Create a LogEntry object that is related to this object.
|
||||
@@ -59,7 +59,6 @@ class LoggingMixin:
|
||||
|
||||
|
||||
class LoggedModel(models.Model, LoggingMixin):
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@@ -74,3 +73,38 @@ class LoggedModel(models.Model, LoggingMixin):
|
||||
return LogEntry.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(type(self)), object_id=self.pk
|
||||
).select_related('user', 'event')
|
||||
|
||||
|
||||
class EventBoundModelMixin:
|
||||
event_lookup = 'event'
|
||||
|
||||
@classmethod
|
||||
def for_event(cls, event):
|
||||
return cls.all.filter(**{
|
||||
cls.event_lookup: event
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def check(cls, **kwargs):
|
||||
try:
|
||||
errors = super(cls).check(**kwargs)
|
||||
except AttributeError:
|
||||
errors = []
|
||||
if hasattr(cls, 'objects'):
|
||||
errors.append(
|
||||
checks.Error(
|
||||
'Default model manager "objects" defined.',
|
||||
hint='Replace the objects manager by a manager called "all".',
|
||||
obj=cls,
|
||||
id='pretixbase.E001',
|
||||
)
|
||||
)
|
||||
if not hasattr(cls, 'all'):
|
||||
errors.append(
|
||||
checks.Error(
|
||||
'Model manager "all" not defined.',
|
||||
obj=cls,
|
||||
id='pretixbase.E002',
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
@@ -234,14 +234,14 @@ class Event(LoggedModel):
|
||||
), tz)
|
||||
|
||||
def copy_data_from(self, other):
|
||||
from . import ItemAddOn, ItemCategory, Item, Question, Quota
|
||||
from . import ItemAddOn, Item, Question, Quota
|
||||
from ..signals import event_copy_data
|
||||
|
||||
self.plugins = other.plugins
|
||||
self.save()
|
||||
|
||||
category_map = {}
|
||||
for c in ItemCategory.objects.filter(event=other):
|
||||
for c in other.categories.all():
|
||||
category_map[c.pk] = c
|
||||
c.pk = None
|
||||
c.event = self
|
||||
|
||||
@@ -14,12 +14,12 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.fields import I18nCharField, I18nTextField
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models.base import LoggedModel
|
||||
from pretix.base.models.base import EventBoundModelMixin, LoggedModel
|
||||
|
||||
from .event import Event
|
||||
|
||||
|
||||
class ItemCategory(LoggedModel):
|
||||
class ItemCategory(EventBoundModelMixin, LoggedModel):
|
||||
"""
|
||||
Items can be sorted into these categories.
|
||||
|
||||
@@ -53,6 +53,8 @@ class ItemCategory(LoggedModel):
|
||||
'source for add-ons.')
|
||||
)
|
||||
|
||||
all = models.Manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Product category")
|
||||
verbose_name_plural = _("Product categories")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import string
|
||||
from datetime import datetime
|
||||
@@ -184,10 +183,6 @@ class Order(LoggedModel):
|
||||
def __str__(self):
|
||||
return self.full_code
|
||||
|
||||
@cached_property
|
||||
def meta_info_data(self):
|
||||
return json.loads(self.meta_info)
|
||||
|
||||
@property
|
||||
def full_code(self):
|
||||
"""
|
||||
|
||||
@@ -414,7 +414,7 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
|
||||
'order': order.code,
|
||||
'secret': order.secret
|
||||
}),
|
||||
'payment_info': str(pprov.order_pending_mail_render(order)),
|
||||
'paymentinfo': str(pprov.order_pending_mail_render(order)),
|
||||
'invoice_name': invoice_name,
|
||||
'invoice_company': invoice_company,
|
||||
},
|
||||
@@ -512,7 +512,7 @@ class OrderChangeManager:
|
||||
if (not variation and item.has_variations) or (variation and variation.item_id != item.pk):
|
||||
raise OrderError(self.error_messages['product_without_variation'])
|
||||
price = item.default_price if variation is None else variation.price
|
||||
if price is None:
|
||||
if not price:
|
||||
raise OrderError(self.error_messages['product_invalid'])
|
||||
self._totaldiff = price - position.price
|
||||
self._quotadiff.update(variation.quotas.all() if variation else item.quotas.all())
|
||||
|
||||
@@ -240,7 +240,7 @@ Your {event} team"""))
|
||||
we successfully received your order for {event} with a total value
|
||||
of {total} {currency}. Please complete your payment before {date}.
|
||||
|
||||
{payment_info}
|
||||
{paymentinfo}
|
||||
|
||||
You can change your order details and view the status of your order at
|
||||
{url}
|
||||
|
||||
@@ -33,7 +33,7 @@ def contextprocessor(request):
|
||||
|
||||
_js_payment_weekdays_disabled = '[]'
|
||||
_nav_event = []
|
||||
if getattr(request, 'event', None) and hasattr(request, 'organizer'):
|
||||
if hasattr(request, 'event'):
|
||||
for receiver, response in nav_event.send(request.event, request=request):
|
||||
_nav_event += response
|
||||
if request.event.settings.get('payment_term_weekdays'):
|
||||
|
||||
@@ -259,12 +259,10 @@ class EventSettingsForm(SettingsForm):
|
||||
)
|
||||
attendee_emails_asked = forms.BooleanField(
|
||||
label=_("Ask for email addresses per ticket"),
|
||||
help_text=_("Normally, pretix asks for one email address per order and the order confirmation will be sent "
|
||||
"only to that email address. If you enable this option, the system will additionally ask for "
|
||||
help_text=_("Normally, pretix asks for one email address per order and the order confirmation will be send "
|
||||
"to that email address. If you enable this option, the system will additionally ask for "
|
||||
"individual email addresses for every admission ticket. This might be useful if you want to "
|
||||
"obtain individual addresses for every attendee even in case of group orders. However, "
|
||||
"pretix will send the order confirmation only to the one primary email address, not to the "
|
||||
"per-attendee addresses."),
|
||||
"obtain individual addresses for every attendee even in case of group orders."),
|
||||
required=False
|
||||
)
|
||||
attendee_emails_required = forms.BooleanField(
|
||||
@@ -492,9 +490,9 @@ class MailSettingsForm(SettingsForm):
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {total}, {currency}, {date}, {payment_info}, {url}, "
|
||||
help_text=_("Available placeholders: {event}, {total}, {currency}, {date}, {paymentinfo}, {url}, "
|
||||
"{invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{total}', '{currency}', '{date}', '{payment_info}',
|
||||
validators=[PlaceholderValidator(['{event}', '{total}', '{currency}', '{date}', '{paymentinfo}',
|
||||
'{url}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_order_paid = I18nFormField(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{% extends "pretixcontrol/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% block title %}{{ request.event.name }}{% endblock %}
|
||||
|
||||
{% block nav %}
|
||||
@@ -113,9 +112,7 @@
|
||||
<li>
|
||||
<a href="{{ nav.url }}" {% if nav.active %}class="active"{% endif %}
|
||||
{% if nav.children %}class="has-children"{% endif %}>
|
||||
{% if nav.icon and "." in nav.icon %}
|
||||
<img src="{% static nav.icon %}" class="fa-img">
|
||||
{% elif nav.icon %}
|
||||
{% if nav.icon %}
|
||||
<i class="fa fa-{{ nav.icon }} fa-fw"></i>
|
||||
{% endif %}
|
||||
{{ nav.label }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.db.models import F, Prefetch, Q
|
||||
from django.db.models import Prefetch, Q
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.views.generic import ListView
|
||||
|
||||
@@ -68,15 +68,12 @@ class CheckInView(EventPermissionRequiredMixin, ListView):
|
||||
'-code': '-order__code',
|
||||
'email': 'order__email',
|
||||
'-email': '-order__email',
|
||||
# Set nulls_first to be consistent over databases
|
||||
'status': F('checkins__id').asc(nulls_first=True),
|
||||
'-status': F('checkins__id').desc(nulls_last=True),
|
||||
'timestamp': F('checkins__datetime').asc(nulls_first=True),
|
||||
'-timestamp': F('checkins__datetime').desc(nulls_last=True),
|
||||
'status': 'checkins__id',
|
||||
'-status': '-checkins__id',
|
||||
'timestamp': 'checkins__datetime',
|
||||
'-timestamp': '-checkins__datetime',
|
||||
'item': 'item__name',
|
||||
'-item': '-item__name',
|
||||
'name': (F('display_name').asc(nulls_first=True),
|
||||
{'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')}),
|
||||
'-name': (F('display_name').desc(nulls_last=True),
|
||||
{'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')}),
|
||||
'name': ('display_name', {'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')}),
|
||||
'-name': ('-display_name', {'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')}),
|
||||
}
|
||||
|
||||
@@ -316,7 +316,8 @@ class InvoicePreview(EventPermissionRequiredMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
pdf = build_preview_invoice_pdf(request.event)
|
||||
resp = HttpResponse(pdf, content_type='application/pdf')
|
||||
resp['Content-Disposition'] = 'attachment; filename="invoice-preview.pdf"'
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="invoice-preview.pdf"'
|
||||
return resp
|
||||
|
||||
|
||||
@@ -436,7 +437,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
def items(self):
|
||||
return {
|
||||
'mail_text_order_placed': ['total', 'currency', 'date', 'invoice_company',
|
||||
'event', 'payment_info', 'url', 'invoice_name'],
|
||||
'event', 'paymentinfo', 'url', 'invoice_name'],
|
||||
'mail_text_order_paid': ['event', 'url', 'invoice_name', 'invoice_company', 'payment_info'],
|
||||
'mail_text_order_free': ['event', 'url', 'invoice_name', 'invoice_company'],
|
||||
'mail_text_resend_link': ['event', 'url', 'invoice_name', 'invoice_company'],
|
||||
@@ -467,7 +468,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
'code': '68CYU2H6ZTP3WLK5',
|
||||
'invoice_name': _('John Doe'),
|
||||
'invoice_company': _('Sample Corporation'),
|
||||
'payment_info': _('Please transfer money to this bank account: 9999-9999-9999-9999')
|
||||
'paymentinfo': _('Please transfer money to this bank account: 9999-9999-9999-9999')
|
||||
}
|
||||
|
||||
def generate_order_url(self, code, secret):
|
||||
@@ -527,7 +528,11 @@ class TicketSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
fname, mimet, data = tickets.preview(self.request.event.pk, self.output.identifier)
|
||||
resp = HttpResponse(data, content_type=mimet)
|
||||
ftype = fname.split(".")[-1]
|
||||
resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype)
|
||||
if mimet == "application/pdf":
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="ticket-preview.{}"'.format(ftype)
|
||||
else:
|
||||
resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype)
|
||||
return resp
|
||||
|
||||
def get_error_url(self) -> str:
|
||||
|
||||
@@ -674,7 +674,7 @@ class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, View)
|
||||
|
||||
if not self.exporter.form.is_valid():
|
||||
messages.error(self.request, _('There was a problem processing your input. See below for error details.'))
|
||||
return self.get(request, *args, **kwargs)
|
||||
return self.get(*args, **kwargs)
|
||||
|
||||
cf = CachedFile()
|
||||
cf.date = now()
|
||||
|
||||
6
src/pretix/helpers/debug.py
Normal file
6
src/pretix/helpers/debug.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from debug_toolbar.middleware import DebugToolbarMiddleware
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
|
||||
class DebugMiddlewareCompatibilityShim(MiddlewareMixin, DebugToolbarMiddleware):
|
||||
pass
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-06-01 10:54+0000\n"
|
||||
"PO-Revision-Date: 2017-06-01 12:56+0200\n"
|
||||
"POT-Creation-Date: 2017-05-18 09:17+0000\n"
|
||||
"PO-Revision-Date: 2017-05-11 12:13+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
@@ -79,71 +79,59 @@ msgid "May 31st, 2017"
|
||||
msgstr "31. Mai 2017"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:164
|
||||
msgid "May 31st – June 4th, 2017"
|
||||
msgstr "31. Mai – 4. Juni 2017"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:165
|
||||
msgid "20:00"
|
||||
msgstr "20:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:166
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:165
|
||||
msgid "19:00"
|
||||
msgstr "19:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:167
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:166
|
||||
msgid "2017-05-31 20:00"
|
||||
msgstr "31.05.2016 20:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:168
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:167
|
||||
msgid "2017-05-31 19:00"
|
||||
msgstr "31.05.2016 19:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:169
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:168
|
||||
msgid "Random City"
|
||||
msgstr "Musterstadt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:170
|
||||
msgid ""
|
||||
"Addon 1\n"
|
||||
"Addon 2"
|
||||
msgstr ""
|
||||
"Workshop 1\n"
|
||||
"Workshop 2"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:215
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:213
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:364
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:362
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:370
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:368
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:372
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:370
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:374
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:372
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:378
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:376
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:614
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:612
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:646
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:644
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchten Sie den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:659
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:657
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-06-01 10:54+0000\n"
|
||||
"PO-Revision-Date: 2017-06-01 12:56+0200\n"
|
||||
"POT-Creation-Date: 2017-05-18 09:17+0000\n"
|
||||
"PO-Revision-Date: 2017-05-11 12:13+0200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
@@ -79,71 +79,59 @@ msgid "May 31st, 2017"
|
||||
msgstr "31. Mai 2017"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:164
|
||||
msgid "May 31st – June 4th, 2017"
|
||||
msgstr "31. Mai – 4. Juni 2017"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:165
|
||||
msgid "20:00"
|
||||
msgstr "20:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:166
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:165
|
||||
msgid "19:00"
|
||||
msgstr "19:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:167
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:166
|
||||
msgid "2017-05-31 20:00"
|
||||
msgstr "31.05.2016 20:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:168
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:167
|
||||
msgid "2017-05-31 19:00"
|
||||
msgstr "31.05.2016 19:00"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:169
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:168
|
||||
msgid "Random City"
|
||||
msgstr "Musterstadt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:170
|
||||
msgid ""
|
||||
"Addon 1\n"
|
||||
"Addon 2"
|
||||
msgstr ""
|
||||
"Workshop 1\n"
|
||||
"Workshop 2"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:215
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:213
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:364
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:362
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:370
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:368
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:372
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:370
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:374
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:372
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:378
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:376
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:614
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:612
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:646
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:644
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchtest du den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:659
|
||||
#: pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/editor.js:657
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
@@ -13,7 +13,6 @@ def parse(data, hint):
|
||||
raise HintMismatchError('Invalid hint')
|
||||
if len(data[0]) != hint['cols']:
|
||||
raise HintMismatchError('Wrong column count')
|
||||
good_hint = False
|
||||
for row in data:
|
||||
resrow = {}
|
||||
if None in row or len(row) != hint['cols']:
|
||||
@@ -32,10 +31,8 @@ def parse(data, hint):
|
||||
or len(resrow['reference']) == 0 or resrow['date'] == '':
|
||||
# This is probably a headline or something other special.
|
||||
continue
|
||||
if resrow['reference'] or resrow['payer']:
|
||||
good_hint = True
|
||||
result.append(resrow)
|
||||
return result, good_hint
|
||||
return result
|
||||
|
||||
|
||||
def get_rows_from_file(file):
|
||||
|
||||
@@ -20,7 +20,7 @@ def parse(file):
|
||||
result.append({
|
||||
'reference': "\n".join([
|
||||
t.data.get(f) for f in ('transaction_details', 'customer_reference', 'bank_reference',
|
||||
'extra_details', 'non_swift_text') if t.data.get(f, '')]),
|
||||
'extra_details') if t.data.get(f, '')]),
|
||||
'amount': str(round_decimal(t.data['amount'].amount)),
|
||||
'date': t.data['date'].isoformat()
|
||||
})
|
||||
|
||||
@@ -84,7 +84,7 @@ def _get_unknown_transactions(event: Event, job: BankImportJob, data: list):
|
||||
amount = Decimal("0.00")
|
||||
|
||||
trans = BankTransaction(event=event, import_job=job,
|
||||
payer=row.get('payer', ''),
|
||||
payer=row['payer'],
|
||||
reference=row['reference'],
|
||||
amount=amount,
|
||||
date=row['date'])
|
||||
|
||||
@@ -14,15 +14,9 @@
|
||||
<dd>{{ payment_info.reference }}</dd>
|
||||
</dl>
|
||||
{% else %}
|
||||
{% if order.status == "p" %}
|
||||
<p>{% blocktrans trimmed %}
|
||||
This order has been marked as paid via bank transfer manually.
|
||||
{% endblocktrans %}</p>
|
||||
{% else %}
|
||||
<p>{% blocktrans trimmed %}
|
||||
This order has been planned to be paid via bank transfer, but no payment has been received yet.
|
||||
{% endblocktrans %}</p>
|
||||
{% endif %}
|
||||
<p>{% blocktrans trimmed %}
|
||||
This order has been planned to be paid via bank transfer, but no payment has been received yet.
|
||||
{% endblocktrans %}</p>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Reference code" %}</dt>
|
||||
<dd>{{ order.full_code }}</dd>
|
||||
|
||||
@@ -275,14 +275,12 @@ class ImportView(EventPermissionRequiredMixin, ListView):
|
||||
|
||||
if self.request.event.settings.get('banktransfer_csvhint') is not None:
|
||||
hint = self.request.event.settings.get('banktransfer_csvhint', as_type=dict)
|
||||
|
||||
try:
|
||||
parsed, good = csvimport.parse(data, hint)
|
||||
parsed = csvimport.parse(data, hint)
|
||||
except csvimport.HintMismatchError: # TODO: narrow down
|
||||
logger.exception('Import using stored hint failed')
|
||||
else:
|
||||
if good:
|
||||
return self.start_processing(parsed)
|
||||
return self.start_processing(parsed)
|
||||
|
||||
return self.assign_view(data)
|
||||
|
||||
@@ -310,7 +308,7 @@ class ImportView(EventPermissionRequiredMixin, ListView):
|
||||
logger.error('Import using stored hint failed: ' + str(e))
|
||||
pass
|
||||
else:
|
||||
parsed, __ = csvimport.parse(data, hint)
|
||||
parsed = csvimport.parse(data, hint)
|
||||
return self.start_processing(parsed)
|
||||
|
||||
def process_csv(self):
|
||||
|
||||
@@ -110,7 +110,7 @@ class CSVCheckinList(BaseCheckinList):
|
||||
if form_data['secrets']:
|
||||
row.append(op.secret)
|
||||
if self.event.settings.attendee_emails_asked:
|
||||
row.append(op.attendee_email or (op.addon_to.attendee_email if op.addon_to else ''))
|
||||
row.append(op.attendee_email or (op.addon_to.attendee_name if op.addon_to else ''))
|
||||
acache = {}
|
||||
for a in op.answers.all():
|
||||
acache[a.question_id] = str(a)
|
||||
|
||||
@@ -161,13 +161,11 @@ var editor = {
|
||||
"attendee_name": gettext("John Doe"),
|
||||
"event_name": gettext("Sample event name"),
|
||||
"event_date": gettext("May 31st, 2017"),
|
||||
"event_date_range": gettext("May 31st – June 4th, 2017"),
|
||||
"event_begin_time": gettext("20:00"),
|
||||
"event_admission_time": gettext("19:00"),
|
||||
"event_begin": gettext("2017-05-31 20:00"),
|
||||
"event_admission": gettext("2017-05-31 19:00"),
|
||||
"event_location": gettext("Random City"),
|
||||
"addons": gettext("Addon 1\nAddon 2"),
|
||||
"event_location": gettext("Random City")
|
||||
},
|
||||
|
||||
_load_pdf: function (dump) {
|
||||
|
||||
@@ -267,13 +267,11 @@
|
||||
<option value="attendee_name">{% trans "Attendee name" %}</option>
|
||||
<option value="event_name">{% trans "Event name" %}</option>
|
||||
<option value="event_date">{% trans "Event date" %}</option>
|
||||
<option value="event_date_range">{% trans "Event date range" %}</option>
|
||||
<option value="event_begin">{% trans "Event begin date and time" %}</option>
|
||||
<option value="event_begin_time">{% trans "Event begin time" %}</option>
|
||||
<option value="event_admission">{% trans "Event admission date and time" %}</option>
|
||||
<option value="event_admission_time">{% trans "Event admission time" %}</option>
|
||||
<option value="event_location">{% trans "Event location" %}</option>
|
||||
<option value="addons">{% trans "List of Add-Ons" %}</option>
|
||||
<option value="other">{% trans "Other…" %}</option>
|
||||
</select>
|
||||
<textarea type="text" value="" class="input-block-level form-control"
|
||||
|
||||
@@ -85,8 +85,6 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
return str(order.event.location).replace("\n", "<br/>\n")
|
||||
elif o['content'] == 'event_date':
|
||||
return order.event.get_date_from_display(show_times=False)
|
||||
elif o['content'] == 'event_date_range':
|
||||
return order.event.get_date_range_display()
|
||||
elif o['content'] == 'event_begin':
|
||||
return order.event.get_date_from_display(show_times=True)
|
||||
elif o['content'] == 'event_begin_time':
|
||||
@@ -99,11 +97,6 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
if order.event.date_admission:
|
||||
tz = timezone(order.event.settings.timezone)
|
||||
return date_format(order.event.date_admission.astimezone(tz), "TIME_FORMAT")
|
||||
elif o['content'] == 'addons':
|
||||
return "<br/>".join([
|
||||
'{} - {}'.format(p.item, p.variation) if p.variation else str(p.item)
|
||||
for p in op.addons.select_related('item', 'variation')
|
||||
])
|
||||
return ''
|
||||
|
||||
def _draw_textarea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
||||
@@ -233,9 +226,9 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
"fontfamily": "Open Sans", "bold": False, "italic": False, "width": "110.00", "content": "attendee_name",
|
||||
"text": "John Doe", "align": "left"},
|
||||
{"type": "textarea", "left": "17.50", "bottom": "242.10", "fontsize": "13.0", "color": [0, 0, 0, 1],
|
||||
"fontfamily": "Open Sans", "bold": False, "italic": False, "width": "110.00",
|
||||
"content": "event_date_range", "text": "May 31st, 2017", "align": "left"},
|
||||
{"type": "textarea", "left": "17.50", "bottom": "204.80", "fontsize": "13.0", "color": [0, 0, 0, 1],
|
||||
"fontfamily": "Open Sans", "bold": False, "italic": False, "width": "110.00", "content": "event_date",
|
||||
"text": "May 31st, 2017", "align": "left"},
|
||||
{"type": "textarea", "left": "17.50", "bottom": "234.30", "fontsize": "13.0", "color": [0, 0, 0, 1],
|
||||
"fontfamily": "Open Sans", "bold": False, "italic": False, "width": "110.00", "content": "event_location",
|
||||
"text": "Random City", "align": "left"},
|
||||
{"type": "textarea", "left": "17.50", "bottom": "194.50", "fontsize": "13.0", "color": [0, 0, 0, 1],
|
||||
|
||||
@@ -86,7 +86,6 @@ class EditorView(EventPermissionRequiredMixin, ChartContainingView, TemplateView
|
||||
if "preview" in request.POST:
|
||||
with rolledback_transaction(), language(request.event.settings.locale):
|
||||
item = request.event.items.create(name=_("Sample product"), default_price=42.23)
|
||||
item2 = request.event.items.create(name=_("Sample workshop"), default_price=23.40)
|
||||
|
||||
from pretix.base.models import Order
|
||||
order = request.event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
|
||||
@@ -94,8 +93,6 @@ class EditorView(EventPermissionRequiredMixin, ChartContainingView, TemplateView
|
||||
expires=now(), code="PREVIEW1234", total=119)
|
||||
|
||||
p = order.positions.create(item=item, attendee_name=_("John Doe"), price=item.default_price)
|
||||
order.positions.create(item=item2, attendee_name=_("John Doe"), price=item.default_price, addon_to=p)
|
||||
order.positions.create(item=item2, attendee_name=_("John Doe"), price=item.default_price, addon_to=p)
|
||||
|
||||
prov = PdfTicketOutput(request.event,
|
||||
override_layout=(json.loads(request.POST.get("data"))
|
||||
@@ -105,7 +102,8 @@ class EditorView(EventPermissionRequiredMixin, ChartContainingView, TemplateView
|
||||
|
||||
resp = HttpResponse(data, content_type=mimet)
|
||||
ftype = fname.split(".")[-1]
|
||||
resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype)
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="ticket-preview.{}"'.format(ftype)
|
||||
return resp
|
||||
elif "data" in request.POST:
|
||||
if cf:
|
||||
|
||||
@@ -19,8 +19,7 @@ from pretix.presale.forms.checkout import (
|
||||
AddOnsForm, ContactForm, InvoiceAddressForm,
|
||||
)
|
||||
from pretix.presale.signals import (
|
||||
checkout_confirm_messages, checkout_flow_steps, contact_form_fields,
|
||||
order_meta_from_request,
|
||||
checkout_confirm_messages, checkout_flow_steps, order_meta_from_request,
|
||||
)
|
||||
from pretix.presale.views import CartMixin, get_cart, get_cart_total
|
||||
from pretix.presale.views.async import AsyncAction
|
||||
@@ -256,13 +255,10 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
||||
|
||||
@cached_property
|
||||
def contact_form(self):
|
||||
initial = {
|
||||
'email': self.request.session.get('email', '')
|
||||
}
|
||||
initial.update(self.request.session.get('contact_form_data', {}))
|
||||
return ContactForm(data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
initial=initial)
|
||||
initial={
|
||||
'email': self.request.session.get('email', '')
|
||||
})
|
||||
|
||||
@cached_property
|
||||
def invoice_address(self):
|
||||
@@ -294,7 +290,6 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
||||
if request.event.settings.invoice_address_asked:
|
||||
addr = self.invoice_form.save()
|
||||
request.session['invoice_address'] = addr.pk
|
||||
request.session['contact_form_data'] = self.contact_form.cleaned_data
|
||||
|
||||
return redirect(self.get_next_url(request))
|
||||
|
||||
@@ -440,18 +435,6 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
||||
ctx['payment_provider'] = self.payment_provider
|
||||
ctx['addr'] = self.invoice_address
|
||||
ctx['confirm_messages'] = self.confirm_messages
|
||||
|
||||
ctx['contact_info'] = []
|
||||
responses = contact_form_fields.send(self.event)
|
||||
for r, response in sorted(responses, key=lambda r: str(r[0])):
|
||||
for key, value in response.items():
|
||||
v = self.request.session.get('contact_form_data', {}).get(key)
|
||||
if v is True:
|
||||
v = _('Yes')
|
||||
elif v is False:
|
||||
v = _('No')
|
||||
ctx['contact_info'].append((value.label, v))
|
||||
|
||||
return ctx
|
||||
|
||||
@cached_property
|
||||
@@ -502,12 +485,9 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
||||
})
|
||||
return redirect(self.get_error_url())
|
||||
|
||||
meta_info = {
|
||||
'contact_form_data': self.request.session.get('contact_form_data', {})
|
||||
}
|
||||
meta_info = {}
|
||||
for receiver, response in order_meta_from_request.send(sender=request.event, request=request):
|
||||
meta_info.update(response)
|
||||
|
||||
return self.do(self.request.event.id, self.payment_provider.identifier,
|
||||
[p.id for p in self.positions], request.session.get('email'),
|
||||
translation.get_language(), self.invoice_address.pk, meta_info)
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
from decimal import Decimal
|
||||
from itertools import chain
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Count, Prefetch, Q
|
||||
from django.forms.widgets import RadioChoiceInput, RadioFieldRenderer
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.formats import number_format
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from pretix.base.models import ItemVariation, Question
|
||||
from pretix.base.models.orders import InvoiceAddress
|
||||
from pretix.base.templatetags.rich_text import rich_text
|
||||
from pretix.presale.signals import contact_form_fields
|
||||
|
||||
|
||||
class ContactForm(forms.Form):
|
||||
@@ -22,16 +23,6 @@ class ContactForm(forms.Form):
|
||||
'modifications to your order or download your ticket later.'),
|
||||
widget=forms.EmailInput(attrs={'data-typocheck-target': '1'}))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
responses = contact_form_fields.send(self.event)
|
||||
for r, response in sorted(responses, key=lambda r: str(r[0])):
|
||||
for key, value in response.items():
|
||||
# We need to be this explicit, since OrderedDict.update does not retain ordering
|
||||
self.fields[key] = value
|
||||
|
||||
|
||||
class InvoiceAddressForm(forms.ModelForm):
|
||||
|
||||
@@ -164,35 +155,51 @@ class QuestionsForm(forms.Form):
|
||||
self.fields['question_%s' % q.id] = field
|
||||
|
||||
|
||||
class AddOnRadioSelect(forms.RadioSelect):
|
||||
option_template_name = 'pretixpresale/forms/addon_choice_option.html'
|
||||
# The following will get totally different once Django 1.11 is integrated
|
||||
class AddOnVariationSelectInput(RadioChoiceInput):
|
||||
|
||||
def optgroups(self, name, value, attrs=None):
|
||||
attrs = attrs or {}
|
||||
groups = []
|
||||
has_selected = False
|
||||
for index, (option_value, option_label, option_desc) in enumerate(chain(self.choices)):
|
||||
if option_value is None:
|
||||
option_value = ''
|
||||
if isinstance(option_label, (list, tuple)):
|
||||
raise TypeError('Choice groups are not supported here')
|
||||
group_name = None
|
||||
subgroup = []
|
||||
groups.append((group_name, subgroup, index))
|
||||
def __init__(self, name, value, attrs, choice, index):
|
||||
super().__init__(name, value, attrs, choice, index)
|
||||
self.description = force_text(choice[2])
|
||||
|
||||
selected = (
|
||||
force_text(option_value) in value and
|
||||
(has_selected is False or self.allow_multiple_selected)
|
||||
def render(self, name=None, value=None, attrs=None):
|
||||
if self.id_for_label:
|
||||
label_for = format_html(' for="{}"', self.id_for_label)
|
||||
else:
|
||||
label_for = ''
|
||||
attrs = dict(self.attrs, **attrs) if attrs else self.attrs
|
||||
if self.description:
|
||||
return format_html(
|
||||
'<label{}>{} {}</label> <span class="fa fa-info-circle toggle-variation-description"></span>'
|
||||
'<div class="variation-description addon-variation-description">{}</div>',
|
||||
label_for, self.tag(attrs), self.choice_label,
|
||||
rich_text(str(self.description))
|
||||
)
|
||||
else:
|
||||
return format_html(
|
||||
'<label{}>{} {}</label>',
|
||||
label_for, self.tag(attrs), self.choice_label,
|
||||
)
|
||||
if selected is True and has_selected is False:
|
||||
has_selected = True
|
||||
attrs['description'] = option_desc
|
||||
subgroup.append(self.create_option(
|
||||
name, option_value, option_label, selected, index,
|
||||
subindex=None, attrs=attrs,
|
||||
))
|
||||
|
||||
return groups
|
||||
|
||||
class AddOnVariationSelectRenderer(RadioFieldRenderer):
|
||||
choice_input_class = AddOnVariationSelectInput
|
||||
|
||||
def render(self):
|
||||
id_ = self.attrs.get('id')
|
||||
output = []
|
||||
for i, choice in enumerate(self.choices):
|
||||
w = self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, i)
|
||||
output.append(format_html(self.inner_html, choice_value=force_text(w), sub_widgets=''))
|
||||
return format_html(
|
||||
self.outer_html,
|
||||
id_attr=format_html(' id="{}"', id_) if id_ else '',
|
||||
content=mark_safe('\n'.join(output)),
|
||||
)
|
||||
|
||||
|
||||
class AddOnVariationSelect(forms.RadioSelect):
|
||||
renderer = AddOnVariationSelectRenderer
|
||||
|
||||
|
||||
class AddOnVariationField(forms.ChoiceField):
|
||||
@@ -300,7 +307,7 @@ class AddOnsForm(forms.Form):
|
||||
choices=choices,
|
||||
label=i.name,
|
||||
required=False,
|
||||
widget=AddOnRadioSelect,
|
||||
widget=AddOnVariationSelect,
|
||||
help_text=rich_text(str(i.description)),
|
||||
initial=current_addons.get(i.pk),
|
||||
)
|
||||
|
||||
@@ -69,18 +69,6 @@ You will recieve the request triggering the order creation as the ``request`` ke
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
contact_form_fields = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
"""
|
||||
This signals allows you to add form fields to the contact form that is presented during checkout
|
||||
and by default only asks for the email address. You are supposed to return a dictionary of
|
||||
form fields with globally unique keys. The validated form results will be saved into the
|
||||
``contact_form_data`` entry of the order metadata dictionary.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_info = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<head>
|
||||
<title>{% block thetitle %}{% endblock %}</title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/x-scss" href="{% static "lightbox/css/lightbox.scss" %}" />
|
||||
<link rel="stylesheet" type="text/css" href="{% static "lightbox/css/lightbox.css" %}" />
|
||||
{% endcompress %}
|
||||
{% if css_file %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ css_file }}"/>
|
||||
|
||||
@@ -111,12 +111,6 @@
|
||||
<dt>{% trans "E-mail address" %}</dt>
|
||||
<dd>{{ request.session.email }}</dd>
|
||||
</dl>
|
||||
{% for l, v in contact_info %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{{ l }}</dt>
|
||||
<dd>{{ v }}</dd>
|
||||
</dl>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{% load rich_text %}
|
||||
<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% include "django/forms/widgets/input.html" %} {{ widget.label }}</label> {% if widget.attrs.description %}<span class="fa fa-info-circle toggle-variation-description"></span>
|
||||
<div class="variation-description addon-variation-description">{{ widget.attrs.description|rich_text }}</div>{% endif %}
|
||||
@@ -581,9 +581,15 @@ class OrderDownload(EventViewMixin, OrderDetailMixin, View):
|
||||
return render(self.request, "pretixbase/cachedfiles/pending.html", {})
|
||||
else:
|
||||
resp = FileResponse(ct.file.file, content_type=ct.type)
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.output.identifier, ct.extension
|
||||
)
|
||||
if ct.type == "application/pdf":
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.output.identifier, ct.extension
|
||||
)
|
||||
else:
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.output.identifier, ct.extension
|
||||
)
|
||||
return resp
|
||||
|
||||
def _download_position(self):
|
||||
@@ -614,10 +620,17 @@ class OrderDownload(EventViewMixin, OrderDetailMixin, View):
|
||||
return render(self.request, "pretixbase/cachedfiles/pending.html", {})
|
||||
else:
|
||||
resp = FileResponse(ct.file.file, content_type=ct.type)
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}-{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.order_position.positionid,
|
||||
self.output.identifier, ct.extension
|
||||
)
|
||||
if ct.type == "application/pdf":
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="{}-{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.order_position.positionid,
|
||||
self.output.identifier, ct.extension
|
||||
)
|
||||
else:
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}-{}-{}-{}{}"'.format(
|
||||
self.request.event.slug.upper(), self.order.code, self.order_position.positionid,
|
||||
self.output.identifier, ct.extension
|
||||
)
|
||||
return resp
|
||||
|
||||
|
||||
@@ -647,5 +660,6 @@ class InvoiceDownload(EventViewMixin, OrderDetailMixin, View):
|
||||
return redirect(self.get_order_url())
|
||||
|
||||
resp = FileResponse(invoice.file.file, content_type='application/pdf')
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}.pdf"'.format(invoice.number)
|
||||
resp['Content-Security-Policy'] = "style-src 'unsafe-inline'; script-src 'unsafe-inline'; object-src 'self'"
|
||||
resp['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(invoice.number)
|
||||
return resp
|
||||
|
||||
@@ -83,7 +83,7 @@ PRETIX_PASSWORD_RESET = config.getboolean('pretix', 'password_reset', fallback=T
|
||||
SITE_URL = config.get('pretix', 'url', fallback='http://localhost')
|
||||
|
||||
PRETIX_PLUGINS_DEFAULT = config.get('pretix', 'plugins_default',
|
||||
fallback='pretix.plugins.sendmail,pretix.plugins.statistics,pretix.plugins.checkinlists')
|
||||
fallback='pretix.plugins.sendmail,pretix.plugins.statistics')
|
||||
|
||||
DEFAULT_CURRENCY = config.get('pretix', 'currency', fallback='EUR')
|
||||
CURRENCIES = list(currencies)
|
||||
@@ -258,7 +258,7 @@ try:
|
||||
import debug_toolbar # noqa
|
||||
if DEBUG:
|
||||
INSTALLED_APPS.append('debug_toolbar.apps.DebugToolbarConfig')
|
||||
MIDDLEWARE.insert(0, 'debug_toolbar.middleware.DebugToolbarMiddleware')
|
||||
MIDDLEWARE.insert(0, 'pretix.helpers.debug.DebugMiddlewareCompatibilityShim')
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -376,9 +376,7 @@ COMPRESS_PRECOMPILERS = (
|
||||
COMPRESS_ENABLED = COMPRESS_OFFLINE = not debug_fallback
|
||||
|
||||
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
|
||||
# 'compressor.filters.css_default.CssAbsoluteFilter',
|
||||
'compressor.filters.css_default.CssAbsoluteFilter',
|
||||
'compressor.filters.cssmin.CSSCompressorFilter',
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Preload images */
|
||||
body:after {
|
||||
content: url(static('lightbox/images/close.png')) url(static('lightbox/images/loading.gif')) url(static('lightbox/images/prev.png')) url(static('lightbox/images/next.png'));
|
||||
content: url(../images/close.png) url(../images/loading.gif) url(../images/prev.png) url(../images/next.png);
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ body:after {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 0 auto;
|
||||
background: url(static('lightbox/images/loading.gif')) no-repeat;
|
||||
background: url(../images/loading.gif) no-repeat;
|
||||
}
|
||||
|
||||
.lb-nav {
|
||||
@@ -110,7 +110,7 @@ body:after {
|
||||
width: 34%;
|
||||
left: 0;
|
||||
float: left;
|
||||
background: url(static('lightbox/images/prev.png')) left 48% no-repeat;
|
||||
background: url(../images/prev.png) left 48% no-repeat;
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.6s;
|
||||
@@ -128,7 +128,7 @@ body:after {
|
||||
width: 64%;
|
||||
right: 0;
|
||||
float: right;
|
||||
background: url(static('lightbox/images/next.png')) right 48% no-repeat;
|
||||
background: url(../images/next.png) right 48% no-repeat;
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.6s;
|
||||
@@ -192,7 +192,7 @@ body:after {
|
||||
float: right;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: url(static('lightbox/images/close.png')) top right no-repeat;
|
||||
background: url(../images/close.png) top right no-repeat;
|
||||
text-align: right;
|
||||
outline: none;
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
|
||||
@@ -29,11 +29,6 @@ nav.navbar {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#side-menu img.fa-img {
|
||||
height: auto;
|
||||
width: 1.28571em;
|
||||
}
|
||||
|
||||
nav.navbar .danger, nav.navbar .danger:hover, nav.navbar .danger:active {
|
||||
background: $brand-danger !important;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ function typocheck() {
|
||||
|
||||
$sources.each(function () {
|
||||
$.each($(this).val().toLowerCase().replace('-', '').split(' '), function (i, w) {
|
||||
if (w && w.length > 5) {
|
||||
if (w) {
|
||||
words.push(w);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
django-debug-toolbar==1.8
|
||||
django-debug-toolbar==1.5
|
||||
sqlparse==0.2.1 # pinned due to difficulties with django-debug-toolbar
|
||||
# Testing requirements
|
||||
pep8==1.5.7 # exact requirement by flake8 2.4.0
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# Functional requirements
|
||||
Django>=1.11.*
|
||||
Django>=1.10.7,<1.11
|
||||
python-dateutil
|
||||
pytz
|
||||
django-bootstrap3==8.2.*
|
||||
django-bootstrap3==8.0.*
|
||||
django-formset-js-improved==0.5.0.1
|
||||
django-compressor==2.1.1
|
||||
django-compressor==2.1
|
||||
django-hierarkey==1.0.*
|
||||
reportlab==3.2.*
|
||||
PyPDF2==1.26.*
|
||||
easy-thumbnails==2.4.*
|
||||
easy-thumbnails==2.*
|
||||
django-libsass
|
||||
libsass
|
||||
django-otp==0.3.*
|
||||
python-u2flib-server==4.*
|
||||
django-formtools==2.0
|
||||
django-formtools==1.0
|
||||
celery==4.0.2
|
||||
kombu==4.0.2
|
||||
django-statici18n==1.3.*
|
||||
@@ -28,14 +28,14 @@ django-markup
|
||||
markdown
|
||||
bleach==2.*
|
||||
raven
|
||||
django-i18nfield>=1.0.1
|
||||
django-i18nfield
|
||||
# Stripe
|
||||
stripe==1.22.*
|
||||
# PayPal
|
||||
paypalrestsdk==1.12.*
|
||||
pycparser==2.13 # https://github.com/eliben/pycparser/issues/147
|
||||
# Banktransfer
|
||||
chardet<3.1.0,>=3.0.2
|
||||
chardet>=2.3,<3
|
||||
mt-940==3.2
|
||||
vobject==0.9.*
|
||||
pycountry
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
django-redis==4.8.*
|
||||
django-redis==4.1.*
|
||||
redis==2.10.5
|
||||
|
||||
18
src/setup.py
18
src/setup.py
@@ -62,21 +62,21 @@ setup(
|
||||
|
||||
keywords='tickets web shop ecommerce',
|
||||
install_requires=[
|
||||
'Django==1.11.*',
|
||||
'Django==1.10.*',
|
||||
'python-dateutil==2.4.*',
|
||||
'pytz',
|
||||
'django-bootstrap3==8.2.*',
|
||||
'django-bootstrap3==7.1.*',
|
||||
'django-formset-js-improved==0.5.0.1',
|
||||
'django-compressor==2.1',
|
||||
'django-hierarkey==1.0.*',
|
||||
'reportlab==3.2.*',
|
||||
'easy-thumbnails==2.4.*',
|
||||
'easy-thumbnails==2.*',
|
||||
'PyPDF2==1.26.*',
|
||||
'django-libsass',
|
||||
'libsass',
|
||||
'django-otp==0.3.*',
|
||||
'python-u2flib-server==4.*',
|
||||
'django-formtools==2.0',
|
||||
'django-formtools==1.0',
|
||||
'celery==4.0.2',
|
||||
'kombu==4.0.2',
|
||||
'django-statici18n==1.3.*',
|
||||
@@ -93,18 +93,18 @@ setup(
|
||||
'raven',
|
||||
'paypalrestsdk==1.12.*',
|
||||
'pycparser==2.13',
|
||||
'django-redis==4.7.*',
|
||||
'django-redis==4.1.*',
|
||||
'redis==2.10.5',
|
||||
'stripe==1.22.*',
|
||||
'chardet<3.1.0,>=3.0.2',
|
||||
'mt-940==4.7',
|
||||
'django-i18nfield>=1.0.1',
|
||||
'chardet>=2.3,<3',
|
||||
'mt-940==3.2',
|
||||
'django-i18nfield',
|
||||
'vobject==0.9.*',
|
||||
'pycountry'
|
||||
],
|
||||
extras_require={
|
||||
'dev': [
|
||||
'django-debug-toolbar==1.7',
|
||||
'django-debug-toolbar==1.5',
|
||||
'sqlparse==0.2.1',
|
||||
'pep8==1.5.7',
|
||||
'pyflakes==1.1.0',
|
||||
|
||||
@@ -92,6 +92,7 @@ class I18nFieldTest(TestCase):
|
||||
"""
|
||||
This test case tests the I18n*Field classes
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
@@ -101,8 +102,8 @@ class I18nFieldTest(TestCase):
|
||||
)
|
||||
|
||||
def test_save_load_cycle_plain_string(self):
|
||||
obj = ItemCategory.objects.create(event=self.event, name="Hello")
|
||||
obj = ItemCategory.objects.get(id=obj.id)
|
||||
obj = ItemCategory.all.create(event=self.event, name="Hello")
|
||||
obj = ItemCategory.all.get(id=obj.id)
|
||||
self.assertIsInstance(obj.name, LazyI18nString)
|
||||
translation.activate('en')
|
||||
self.assertEqual(str(obj.name), "Hello")
|
||||
@@ -110,14 +111,14 @@ class I18nFieldTest(TestCase):
|
||||
self.assertEqual(str(obj.name), "Hello")
|
||||
|
||||
def test_save_load_cycle_i18n_string(self):
|
||||
obj = ItemCategory.objects.create(event=self.event,
|
||||
name=LazyI18nString(
|
||||
{
|
||||
'de': 'Hallo',
|
||||
'en': 'Hello'
|
||||
}
|
||||
))
|
||||
obj = ItemCategory.objects.get(id=obj.id)
|
||||
obj = ItemCategory.all.create(event=self.event,
|
||||
name=LazyI18nString(
|
||||
{
|
||||
'de': 'Hallo',
|
||||
'en': 'Hello'
|
||||
}
|
||||
))
|
||||
obj = ItemCategory.all.get(id=obj.id)
|
||||
self.assertIsInstance(obj.name, LazyI18nString)
|
||||
translation.activate('en')
|
||||
self.assertEqual(str(obj.name), "Hello")
|
||||
|
||||
@@ -687,8 +687,8 @@ class ItemCategoryTest(TestCase):
|
||||
)
|
||||
|
||||
def test_sorting(self):
|
||||
c1 = ItemCategory.objects.create(event=self.event)
|
||||
c2 = ItemCategory.objects.create(event=self.event)
|
||||
c1 = ItemCategory.all.create(event=self.event)
|
||||
c2 = ItemCategory.all.create(event=self.event)
|
||||
assert c1 < c2
|
||||
c1.position = 2
|
||||
c2.position = 1
|
||||
|
||||
@@ -210,12 +210,12 @@ def checkin_list_env():
|
||||
('code', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
|
||||
('-email', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
|
||||
('email', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
|
||||
('-status', ['A3Ticket', 'A1Ticket', 'A1Mascot', 'A2Ticket']),
|
||||
('status', ['A1Mascot', 'A2Ticket', 'A1Ticket', 'A3Ticket']),
|
||||
('-timestamp', ['A1Ticket', 'A3Ticket', 'A1Mascot', 'A2Ticket']), # A1 checkin date > A3 checkin date
|
||||
('timestamp', ['A1Mascot', 'A2Ticket', 'A3Ticket', 'A1Ticket']),
|
||||
('-name', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
|
||||
('name', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']), # mascot doesn't include attendee name
|
||||
# ('-status', ['A3Ticket', 'A1Ticket', 'A1Mascot', 'A2Ticket']),
|
||||
# ('status', ['A1Mascot', 'A2Ticket', 'A1Ticket', 'A3Ticket']),
|
||||
# ('-timestamp', ['A1Ticket', 'A3Ticket', 'A1Mascot', 'A2Ticket']), # A1 checkin date > A3 checkin date
|
||||
# ('timestamp', ['A1Mascot', 'A2Ticket', 'A3Ticket', 'A1Ticket']),
|
||||
# ('-name', ['A3Ticket', 'A2Ticket', 'A1Ticket', 'A1Mascot']),
|
||||
# ('name', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']), # mascot doesn't include attendee name
|
||||
('-item', ['A1Ticket', 'A2Ticket', 'A3Ticket', 'A1Mascot']),
|
||||
('item', ['A1Mascot', 'A1Ticket', 'A2Ticket', 'A3Ticket']),
|
||||
])
|
||||
@@ -259,7 +259,8 @@ def test_checkins_item_filter(client, checkin_list_env):
|
||||
@pytest.mark.parametrize("query, expected", [
|
||||
('status=&item=&user=&ordering=', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']),
|
||||
('status=1&item=&user=&ordering=timestamp', ['A3Ticket', 'A1Ticket']),
|
||||
('status=0&item=&user=&ordering=-name', ['A2Ticket', 'A1Mascot']),
|
||||
# ('status=0&item=&user=&ordering=-name', ['A2Ticket', 'A1Mascot']),
|
||||
# ('status=&item=Ticket&user=&ordering=checkins__datetime', ['A2Ticket', 'A3Ticket', 'A1Ticket']),
|
||||
])
|
||||
def test_checkins_list_mixed(client, checkin_list_env, query, expected):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
@@ -288,8 +289,8 @@ def checkin_list_with_addon_env():
|
||||
team.limit_events.add(event)
|
||||
|
||||
# item
|
||||
cat_adm = ItemCategory.objects.create(event=event, name="Admission")
|
||||
cat_workshop = ItemCategory.objects.create(event=event, name="Admission", is_addon=True)
|
||||
cat_adm = ItemCategory.all.create(event=event, name="Admission")
|
||||
cat_workshop = ItemCategory.all.create(event=event, name="Admission", is_addon=True)
|
||||
item_ticket = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True, category=cat_adm)
|
||||
item_workshop = Item.objects.create(event=event, name="Workshop", default_price=10, admission=False,
|
||||
category=cat_workshop)
|
||||
|
||||
@@ -68,7 +68,7 @@ class EventsTest(SoupTest):
|
||||
assert len(doc.select(".alert-success")) > 0
|
||||
# date_to should not be changed even though the timezone is changed
|
||||
assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00"
|
||||
assert 'selected' in doc.find('option', {"value": "Asia/Tokyo"}).attrs
|
||||
assert doc.find('option', {"value": "Asia/Tokyo"})['selected'] == "selected"
|
||||
assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12"
|
||||
|
||||
self.event1.refresh_from_db()
|
||||
|
||||
@@ -37,7 +37,7 @@ class CategoriesTest(ItemFormTest):
|
||||
self.assertIn("Entry tickets", doc.select("#page-wrapper table")[0].text)
|
||||
|
||||
def test_update(self):
|
||||
c = ItemCategory.objects.create(event=self.event1, name="Entry tickets")
|
||||
c = ItemCategory.all.create(event=self.event1, name="Entry tickets")
|
||||
doc = self.get_doc('/control/event/%s/%s/categories/%s/' % (self.orga1.slug, self.event1.slug, c.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
form_data['name_0'] = 'T-Shirts'
|
||||
@@ -46,11 +46,11 @@ class CategoriesTest(ItemFormTest):
|
||||
assert doc.select(".alert-success")
|
||||
self.assertIn("T-Shirts", doc.select("#page-wrapper table")[0].text)
|
||||
self.assertNotIn("Entry tickets", doc.select("#page-wrapper table")[0].text)
|
||||
assert str(ItemCategory.objects.get(id=c.id).name) == 'T-Shirts'
|
||||
assert str(ItemCategory.all.get(id=c.id).name) == 'T-Shirts'
|
||||
|
||||
def test_sort(self):
|
||||
c1 = ItemCategory.objects.create(event=self.event1, name="Entry tickets", position=0)
|
||||
ItemCategory.objects.create(event=self.event1, name="T-Shirts", position=1)
|
||||
c1 = ItemCategory.all.create(event=self.event1, name="Entry tickets", position=0)
|
||||
ItemCategory.all.create(event=self.event1, name="T-Shirts", position=1)
|
||||
doc = self.get_doc('/control/event/%s/%s/categories/' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("Entry tickets", doc.select("table > tbody > tr")[0].text)
|
||||
self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text)
|
||||
@@ -66,14 +66,14 @@ class CategoriesTest(ItemFormTest):
|
||||
self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text)
|
||||
|
||||
def test_delete(self):
|
||||
c = ItemCategory.objects.create(event=self.event1, name="Entry tickets")
|
||||
c = ItemCategory.all.create(event=self.event1, name="Entry tickets")
|
||||
doc = self.get_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id),
|
||||
form_data)
|
||||
assert doc.select(".alert-success")
|
||||
self.assertNotIn("Entry tickets", doc.select("#page-wrapper")[0].text)
|
||||
assert not ItemCategory.objects.filter(id=c.id).exists()
|
||||
assert not ItemCategory.all.filter(id=c.id).exists()
|
||||
|
||||
|
||||
class QuestionsTest(ItemFormTest):
|
||||
@@ -264,7 +264,7 @@ class ItemsTest(ItemFormTest):
|
||||
require_voucher=True, allow_cancel=False)
|
||||
self.var1 = ItemVariation.objects.create(item=self.item2, value="Silver")
|
||||
self.var2 = ItemVariation.objects.create(item=self.item2, value="Gold")
|
||||
self.addoncat = ItemCategory.objects.create(event=self.event1, name="Item category")
|
||||
self.addoncat = ItemCategory.all.create(event=self.event1, name="Item category")
|
||||
|
||||
def test_move(self):
|
||||
self.client.post('/control/event/%s/%s/items/%s/down' % (self.orga1.slug, self.event1.slug, self.item1.id),)
|
||||
|
||||
@@ -141,7 +141,7 @@ class MailSettingPreviewTest(SoupTest):
|
||||
assert res['msgs']['en'] == self.locale_event.name['en']
|
||||
|
||||
def test_mail_text_order_placed(self):
|
||||
text = '{event}{total}{currency}{date}{payment_info}{url}{invoice_name}{invoice_company}'
|
||||
text = '{event}{total}{currency}{date}{paymentinfo}{url}{invoice_name}{invoice_company}'
|
||||
response = self.client.post(self.target.format(
|
||||
self.orga1.slug, self.event1.slug), {
|
||||
'item': 'mail_text_order_placed',
|
||||
|
||||
@@ -26,7 +26,7 @@ def item(event):
|
||||
|
||||
@pytest.fixture
|
||||
def item_category(event):
|
||||
return ItemCategory.objects.create(event=event)
|
||||
return ItemCategory.all.create(event=event)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -15,7 +15,7 @@ class CsvImportTest(TestCase):
|
||||
with open(os.path.join(DATA_DIR, filename), 'rb') as f:
|
||||
data = csvimport.get_rows_from_file(f)
|
||||
self.assertEqual(data, expected)
|
||||
parsed, good = csvimport.parse(data, hint)
|
||||
parsed = csvimport.parse(data, hint)
|
||||
self.assertEqual(parsed, expected_parsed)
|
||||
|
||||
def test_sample_file_bbbank(self):
|
||||
@@ -125,7 +125,7 @@ class CsvImportTest(TestCase):
|
||||
def test_sample_file_postbank(self):
|
||||
expected = [
|
||||
['Buchungstag', 'Wertstellung', 'Umsatzart', 'Buchungsdetails', 'Auftraggeber', 'Empfänger',
|
||||
'Betrag (€)', 'Saldo (€)'],
|
||||
'Betrag (\x80)', 'Saldo (\x80)'],
|
||||
['07.08.2016', '01.08.2016', 'Gutschrift', 'Verwendungszweck 2015ABCDE', 'Karla Kundin',
|
||||
'Fiktive Veranstaltungsgesellschaft mbH', '\xA4 42,00', '\xA4 1.337,42'],
|
||||
['29.07.2016', '29.07.2016', 'Gutschrift', 'Referenz NOTPROVIDED', 'Lars Lieferant',
|
||||
|
||||
@@ -18,7 +18,7 @@ def env(client):
|
||||
plugins='pretix.plugins.paypal',
|
||||
live=True
|
||||
)
|
||||
category = ItemCategory.objects.create(event=event, name="Everything", position=0)
|
||||
category = ItemCategory.all.create(event=event, name="Everything", position=0)
|
||||
quota_tickets = Quota.objects.create(event=event, name='Tickets', size=5)
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket',
|
||||
category=category, default_price=23, admission=True)
|
||||
|
||||
@@ -27,7 +27,7 @@ def env(client):
|
||||
plugins='pretix.plugins.stripe',
|
||||
live=True
|
||||
)
|
||||
category = ItemCategory.objects.create(event=event, name="Everything", position=0)
|
||||
category = ItemCategory.all.create(event=event, name="Everything", position=0)
|
||||
quota_tickets = Quota.objects.create(event=event, name='Tickets', size=5)
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket',
|
||||
category=category, default_price=23, admission=True)
|
||||
|
||||
@@ -30,7 +30,7 @@ def item(event):
|
||||
@pytest.fixture
|
||||
def item_category(event):
|
||||
"""Returns an item category instance"""
|
||||
return ItemCategory.objects.create(event=event)
|
||||
return ItemCategory.all.create(event=event)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -24,7 +24,7 @@ class CartTestMixin:
|
||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
||||
live=True
|
||||
)
|
||||
self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0)
|
||||
self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0)
|
||||
self.quota_shirts = Quota.objects.create(event=self.event, name='Shirts', size=2)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12)
|
||||
self.quota_shirts.items.add(self.shirt)
|
||||
@@ -1013,7 +1013,7 @@ class CartTest(CartTestMixin, TestCase):
|
||||
class CartAddonTest(CartTestMixin, TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.workshopcat = ItemCategory.objects.create(name="Workshops", is_addon=True, event=self.event)
|
||||
self.workshopcat = ItemCategory.all.create(name="Workshops", is_addon=True, event=self.event)
|
||||
self.workshopquota = Quota.objects.create(event=self.event, name='Workshop 1', size=5)
|
||||
self.workshop1 = Item.objects.create(event=self.event, name='Workshop 1',
|
||||
category=self.workshopcat, default_price=12)
|
||||
|
||||
@@ -24,7 +24,7 @@ class CheckoutTestCase(TestCase):
|
||||
plugins='pretix.plugins.stripe,pretix.plugins.banktransfer',
|
||||
live=True
|
||||
)
|
||||
self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0)
|
||||
self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0)
|
||||
self.quota_tickets = Quota.objects.create(event=self.event, name='Tickets', size=5)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
|
||||
category=self.category, default_price=23, admission=True)
|
||||
@@ -36,7 +36,7 @@ class CheckoutTestCase(TestCase):
|
||||
self.session_key = self.client.cookies.get(settings.SESSION_COOKIE_NAME).value
|
||||
self._set_session('email', 'admin@localhost')
|
||||
|
||||
self.workshopcat = ItemCategory.objects.create(name="Workshops", is_addon=True, event=self.event)
|
||||
self.workshopcat = ItemCategory.all.create(name="Workshops", is_addon=True, event=self.event)
|
||||
self.workshopquota = Quota.objects.create(event=self.event, name='Workshop 1', size=5)
|
||||
self.workshop1 = Item.objects.create(event=self.event, name='Workshop 1',
|
||||
category=self.workshopcat, default_price=12)
|
||||
|
||||
@@ -116,7 +116,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.assertNotIn("Early-bird", html)
|
||||
|
||||
def test_simple_with_category(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0)
|
||||
q.items.add(item)
|
||||
@@ -125,13 +125,13 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.assertIn("Early-bird", doc.select("section:nth-of-type(1) div:nth-of-type(1)")[0].text)
|
||||
|
||||
def test_simple_without_quota(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0)
|
||||
resp = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
self.assertNotIn("Early-bird", resp.rendered_content)
|
||||
|
||||
def test_no_variations_in_quota(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0)
|
||||
ItemVariation.objects.create(item=item, value='Blue')
|
||||
@@ -140,7 +140,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.assertNotIn("Early-bird", resp.rendered_content)
|
||||
|
||||
def test_one_variation_in_quota(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0)
|
||||
var1 = ItemVariation.objects.create(item=item, value='Red')
|
||||
@@ -150,7 +150,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self._assert_variation_found()
|
||||
|
||||
def test_one_variation_in_unlimited_quota(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=None)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0)
|
||||
var1 = ItemVariation.objects.create(item=item, value='Red')
|
||||
@@ -166,7 +166,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.assertNotIn("Black", doc.select("section:nth-of-type(1)")[0].text)
|
||||
|
||||
def test_variation_prices_in_quota(self):
|
||||
c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0)
|
||||
c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=12)
|
||||
var1 = ItemVariation.objects.create(item=item, value='Red', default_price=14, position=1)
|
||||
|
||||
@@ -25,7 +25,7 @@ class OrdersTest(TestCase):
|
||||
self.event.settings.set('payment_banktransfer__enabled', True)
|
||||
self.event.settings.set('ticketoutput_testdummy__enabled', True)
|
||||
|
||||
self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0)
|
||||
self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0)
|
||||
self.quota_shirts = Quota.objects.create(event=self.event, name='Shirts', size=2)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12)
|
||||
self.quota_shirts.items.add(self.shirt)
|
||||
|
||||
Reference in New Issue
Block a user