mirror of
https://github.com/pretix/pretix.git
synced 2026-10-16 21:44:43 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c00cebb724 |
@@ -316,7 +316,6 @@ def mail(email: Union[str, Sequence[str]], subject: Union[str, FormattedString],
|
||||
body_html = None
|
||||
|
||||
m = OutgoingMail.objects.create(
|
||||
guid=guid,
|
||||
organizer=organizer,
|
||||
event=event,
|
||||
order=order,
|
||||
|
||||
@@ -359,8 +359,7 @@ def mark_order_refunded(order, user=None, auth=None, api_token=None):
|
||||
|
||||
def mark_order_expired(order, user=None, auth=None):
|
||||
"""
|
||||
Mark this order as expired. This sets the order status, generates an invoice cancellation
|
||||
and returns the order object.
|
||||
Mark this order as expired. This sets the payment status and returns the order object.
|
||||
:param order: The order to change
|
||||
:param user: The user that performed the change
|
||||
"""
|
||||
|
||||
@@ -752,11 +752,6 @@ def base_placeholders(sender, **kwargs):
|
||||
lambda position_or_address: concatenation_for_salutation(get_best_name(position_or_address, parts=True)),
|
||||
lambda event: concatenation_for_salutation(name_scheme['sample']),
|
||||
))
|
||||
ph.append(SimpleFunctionalTextPlaceholder(
|
||||
"attendee_name_for_salutation", ["position"],
|
||||
lambda position: concatenation_for_salutation(position.attendee_name_parts),
|
||||
lambda event: concatenation_for_salutation(name_scheme['sample']),
|
||||
))
|
||||
|
||||
for f, l, w in name_scheme['fields']:
|
||||
if f == 'full_name':
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load eventurl %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% blocktrans with name=request.organizer.name %}Organizer: {{ name }}{% endblocktrans %}
|
||||
</h1>
|
||||
<div class="helper-space-below">
|
||||
{% trans "Public profile" %}:
|
||||
<span id="organizer_url" class="text-muted">{% abseventurl request.organizer "presale:organizer.index" %}</span>
|
||||
<button type="button" class="btn btn-default btn-xs btn-clipboard js-only" data-clipboard-target="#organizer_url">
|
||||
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
<span class="sr-only">{% trans "Copy to clipboard" %}</span>
|
||||
</button>
|
||||
<div class="btn-group helper-display-inline-block">
|
||||
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" title="{% trans "Create QR code" %}" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-qrcode" aria-hidden="true"></i>
|
||||
</button>
|
||||
{% include "pretixcontrol/organizers/fragment_qr_dropdown.html" with url=0 %}
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% if events|length == 0 and not filter_form.filtered %}
|
||||
{% if "organizer.events:create" in request.orgapermset %}
|
||||
<p>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{% load i18n %}
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li>
|
||||
<a href="{% url "control:organizer.qrcode" organizer=request.organizer.slug filetype="png" %}{% if url %}?url={{ url|urlencode }}{% endif %}"
|
||||
target="_blank" download>
|
||||
{% blocktrans with filetype="PNG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:organizer.qrcode" organizer=request.organizer.slug filetype="svg" %}{% if url %}?url={{ url|urlencode }}{% endif %}"
|
||||
target="_blank" download>
|
||||
{% blocktrans with filetype="SVG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:organizer.qrcode" organizer=request.organizer.slug filetype="jpeg" %}{% if url %}?url={{ url|urlencode }}{% endif %}"
|
||||
target="_blank" download>
|
||||
{% blocktrans with filetype="JPG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:organizer.qrcode" organizer=request.organizer.slug filetype="gif" %}{% if url %}?url={{ url|urlencode }}{% endif %}"
|
||||
target="_blank" download>
|
||||
{% blocktrans with filetype="GIF" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -263,6 +263,7 @@ urlpatterns = [
|
||||
name='organizer.export.scheduled.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/ticket_select2$', typeahead.ticket_select2, name='organizer.ticket_select2'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/datasync/failedjobs/$', datasync.OrganizerFailedSyncJobsView.as_view(), name='organizer.datasync.failedjobs'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/qrcode.(?P<filetype>(png|jpeg|gif|svg))$', organizer.OrganizerQRCode.as_view(), name='organizer.qrcode'),
|
||||
re_path(r'^nav/typeahead/$', typeahead.nav_context_list, name='nav.typeahead'),
|
||||
re_path(r'^events/$', main.EventList.as_view(), name='events'),
|
||||
re_path(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||
|
||||
@@ -40,11 +40,14 @@ from collections import Counter
|
||||
from datetime import time, timedelta
|
||||
from decimal import Decimal
|
||||
from hashlib import sha1
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
from json import JSONDecodeError
|
||||
|
||||
import bleach
|
||||
import dateutil
|
||||
import qrcode
|
||||
import qrcode.image.svg
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
@@ -3758,3 +3761,41 @@ def reorder_channels(request, organizer):
|
||||
)
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
class OrganizerQRCode(OrganizerPermissionRequiredMixin, View):
|
||||
permission = None
|
||||
|
||||
def get(self, request, *args, filetype, **kwargs):
|
||||
url = eventreverse_absolute(request.organizer, 'presale:organizer.index')
|
||||
|
||||
if "url" in request.GET:
|
||||
if request.GET["url"].startswith(url):
|
||||
url = request.GET["url"]
|
||||
else:
|
||||
raise PermissionDenied("Untrusted URL")
|
||||
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_M,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
qr.add_data(url)
|
||||
qr.make(fit=True)
|
||||
|
||||
if filetype == 'svg':
|
||||
factory = qrcode.image.svg.SvgPathImage
|
||||
img = qr.make_image(image_factory=factory)
|
||||
r = HttpResponse(img.to_string(), content_type='image/svg+xml')
|
||||
r['Content-Disposition'] = f'inline; filename="qrcode-{request.organizer.slug}.{filetype}"'
|
||||
return r
|
||||
elif filetype in ('jpeg', 'png', 'gif'):
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
byte_io = BytesIO()
|
||||
img.save(byte_io, filetype.upper())
|
||||
byte_io.seek(0)
|
||||
r = HttpResponse(byte_io.read(), content_type='image/' + filetype)
|
||||
r['Content-Disposition'] = f'inline; filename="qrcode-{request.organizer.slug}.{filetype}"'
|
||||
return r
|
||||
|
||||
@@ -342,7 +342,7 @@ def nav_context_list(request):
|
||||
max_to=Max('subevents__date_to'),
|
||||
max_fromto=Greatest(Max('subevents__date_to'), Max('subevents__date_from'))
|
||||
).annotate(
|
||||
order_from=Coalesce('max_from', 'date_from'),
|
||||
order_from=Coalesce('min_from', 'date_from'),
|
||||
).order_by('-order_from', 'slug')
|
||||
|
||||
if request.user.has_active_staff_session(request.session.session_key):
|
||||
|
||||
@@ -138,7 +138,7 @@ logger = logging.getLogger('pretix.plugins.stripe')
|
||||
# - BLIK: ✗
|
||||
# - Pay By Bank: ✓
|
||||
# - TWINT: ✓
|
||||
# - Wero: ✓
|
||||
# - Wero: ✓ (No settings UI yet)
|
||||
# - giropay: ✗ (deprecated)
|
||||
# - Sofort: ✗ (deprecated)
|
||||
#
|
||||
@@ -529,14 +529,15 @@ class StripeSettingsHolder(BasePaymentProvider):
|
||||
'before they work properly.'),
|
||||
required=False,
|
||||
)),
|
||||
('method_wero',
|
||||
forms.BooleanField(
|
||||
label=_('Wero'),
|
||||
disabled=self.event.currency not in 'EUR',
|
||||
help_text=_('Some payment methods might need to be enabled in the settings of your Stripe account '
|
||||
'before they work properly.'),
|
||||
required=False,
|
||||
)),
|
||||
# Disabled for now, since still in closed Beta and only available to dedicated boarded accounts.
|
||||
# ('method_wero',
|
||||
# forms.BooleanField(
|
||||
# label=_('Wero'),
|
||||
# disabled=self.event.currency not in 'EUR',
|
||||
# help_text=_('Some payment methods might need to be enabled in the settings of your Stripe account '
|
||||
# 'before they work properly.'),
|
||||
# required=False,
|
||||
# )),
|
||||
] + extra_fields + list(super().settings_form_fields.items()) + moto_settings
|
||||
)
|
||||
if not self.settings.connect_client_id or self.settings.secret_key:
|
||||
|
||||
@@ -247,10 +247,6 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
||||
context['has_addon_choices'] = any(cp.has_addon_choices for cp in get_cart(self.request))
|
||||
|
||||
templating_context = PlaceholderContext(event_or_subevent=self.subevent or self.request.event, event=self.request.event)
|
||||
|
||||
for field in ('presale_has_ended_text',):
|
||||
context[field] = templating_context.format(str(self.request.event.settings[field]))
|
||||
|
||||
if self.subevent:
|
||||
context['frontpage_text'] = templating_context.format(str(self.subevent.frontpage_text))
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user