diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index d1348c67d..091616f13 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -10,6 +10,7 @@ from typing import Any, Dict, List, Union import dateutil import pytz from django.conf import settings +from django.contrib import messages from django.db import models, transaction from django.db.models import ( Case, Exists, F, Max, OuterRef, Q, Subquery, Sum, Value, When, @@ -17,6 +18,7 @@ from django.db.models import ( from django.db.models.functions import Coalesce from django.db.models.signals import post_delete from django.dispatch import receiver +from django.shortcuts import redirect from django.urls import reverse from django.utils.crypto import get_random_string from django.utils.encoding import escape_uri_path @@ -460,6 +462,47 @@ class Order(LoggedModel): return self._is_still_available(count_waitinglist=count_waitinglist) + def regenerate_secrets(self, user=None): + self.secret = generate_secret() + for op in self.positions.all(): + op.secret = generate_position_secret() + op.save(update_fields=['secret']) + CachedTicket.objects.filter(order_position__order=self).delete() + CachedCombinedTicket.objects.filter(order=self).delete() + self.log_action('pretix.event.order.secret.changed', user=user) + self.save(update_fields=['secret']) + + def resend_link(self, user=None): + from pretix.base.services.mail import SendMailException + from pretix.multidomain.urlreverse import build_absolute_uri + + with language(self.locale): + try: + try: + invoice_name = self.invoice_address.name + invoice_company = self.invoice_address.company + except InvoiceAddress.DoesNotExist: + invoice_name = "" + invoice_company = "" + email_template = self.event.settings.mail_text_resend_link + email_context = { + 'event': self.event.name, + 'url': build_absolute_uri(self.event, 'presale:event.order', kwargs={ + 'order': self.code, + 'secret': self.secret + }), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + } + email_subject = _('Your order: %(code)s') % {'code': self.code} + self.send_mail( + email_subject, email_template, email_context, + 'pretix.event.order.email.resend', user=user + ) + except SendMailException: + messages.error(self.request, _('There was an error sending the mail. Please try again later.')) + return redirect(self.get_order_url()) + def _is_still_available(self, now_dt: datetime=None, count_waitinglist=True) -> Union[bool, str]: error_messages = { 'unavailable': _('The ordered product "{item}" is no longer available.'), diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index e7d980093..f03c66a0e 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -30,7 +30,6 @@ from pretix.base.i18n import language from pretix.base.models import ( CachedCombinedTicket, CachedFile, CachedTicket, Invoice, InvoiceAddress, Item, ItemVariation, LogEntry, Order, QuestionAnswer, Quota, - generate_position_secret, generate_secret, ) from pretix.base.models.event import SubEvent from pretix.base.models.orders import OrderFee, OrderPayment, OrderRefund @@ -845,33 +844,7 @@ class OrderResendLink(OrderView): permission = 'can_change_orders' def post(self, *args, **kwargs): - with language(self.order.locale): - try: - try: - invoice_name = self.order.invoice_address.name - invoice_company = self.order.invoice_address.company - except InvoiceAddress.DoesNotExist: - invoice_name = "" - invoice_company = "" - email_template = self.order.event.settings.mail_text_resend_link - email_context = { - 'event': self.order.event.name, - 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ - 'order': self.order.code, - 'secret': self.order.secret - }), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - } - email_subject = _('Your order: %(code)s') % {'code': self.order.code} - self.order.send_mail( - email_subject, email_template, email_context, - 'pretix.event.order.email.resend', user=self.request.user - ) - except SendMailException: - messages.error(self.request, _('There was an error sending the mail. Please try again later.')) - return redirect(self.get_order_url()) - + self.order.resend_link(self.request.user) messages.success(self.request, _('The email has been queued to be sent.')) return redirect(self.get_order_url()) @@ -1166,13 +1139,7 @@ class OrderContactChange(OrderView): ) if self.form.cleaned_data['regenerate_secrets']: changed = True - self.order.secret = generate_secret() - for op in self.order.positions.all(): - op.secret = generate_position_secret() - op.save() - CachedTicket.objects.filter(order_position__order=self.order).delete() - CachedCombinedTicket.objects.filter(order=self.order).delete() - self.order.log_action('pretix.event.order.secret.changed', user=self.request.user) + self.order.regenerate_secrets(self.request.user) self.form.save() if changed: diff --git a/src/pretix/presale/forms/order.py b/src/pretix/presale/forms/order.py new file mode 100644 index 000000000..4c14d870c --- /dev/null +++ b/src/pretix/presale/forms/order.py @@ -0,0 +1,33 @@ +from django import forms +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ + +from pretix.base.validators import EmailBlacklistValidator + + +class ChangeContactForm(forms.Form): + email = forms.EmailField(label=_('E-mail'), + help_text=_('Make sure to enter a valid email address. We will send an email containing ' + 'the new link to the ticket there.'), + validators=[EmailBlacklistValidator()]) + email_repeat = forms.EmailField( + label=_('E-mail address (repeated)'), + help_text=_('Please enter the same email address again to make sure you typed it correctly.') + ) + check_noaccess = forms.BooleanField( + label=_('I have understood that after this operation, I will no longer have access to these tickets. The link ' + 'of the ticket order will be changed and the new link will be sent to the given email address.') + ) + check_printed = forms.BooleanField( + label=_('I have understood that after this operation, all printed or downloaded tickets from this order will ' + 'be invalid and need to be downloaded again.') + ) + check_data = forms.BooleanField( + label=_('I have understood that after this operation, the new owner will have access to all personal data ' + 'included in my ticket order, such as information given for the tickets, my invoicing address, or ' + 'previous invoices.') + ) + + def clean(self): + if self.cleaned_data.get('email').lower() != self.cleaned_data.get('email_repeat').lower(): + raise ValidationError(_('Please enter the same email address twice.')) diff --git a/src/pretix/presale/templates/pretixpresale/event/order.html b/src/pretix/presale/templates/pretixpresale/event/order.html index 914f812ff..747eb8f1a 100644 --- a/src/pretix/presale/templates/pretixpresale/event/order.html +++ b/src/pretix/presale/templates/pretixpresale/event/order.html @@ -223,17 +223,24 @@ {% endif %}
- {% if order.can_user_cancel %} -+
+ {% if order.status == "p" or order.status == "n" or order.status == "e" %} + + + {% trans "Transfer order" %} + + {% endif %} + {% if order.can_user_cancel %} {% trans "Cancel order" %} -
-