Add support for orders without email addresses

This commit is contained in:
Raphael Michel
2018-02-04 22:42:41 +01:00
parent a5af7a70f3
commit 4ccf33af03
12 changed files with 83 additions and 56 deletions

View File

@@ -21,7 +21,7 @@ class MailExporter(BaseExporter):
pos = OrderPosition.objects.filter( pos = OrderPosition.objects.filter(
order__event=self.event, order__status__in=form_data['status'] order__event=self.event, order__status__in=form_data['status']
).values('attendee_email') ).values('attendee_email')
data = "\r\n".join(set(a['email'] for a in addrs) data = "\r\n".join(set(a['email'] for a in addrs if a['email'])
| set(a['attendee_email'] for a in pos if a['attendee_email'])) | set(a['attendee_email'] for a in pos if a['attendee_email']))
return '{}_pretixemails.txt'.format(self.event.slug), 'text/plain', data.encode("utf-8") return '{}_pretixemails.txt'.format(self.event.slug), 'text/plain', data.encode("utf-8")

View File

@@ -395,6 +395,9 @@ class Order(LoggedModel):
""" """
from pretix.base.services.mail import SendMailException, mail, render_mail from pretix.base.services.mail import SendMailException, mail, render_mail
if not self.email:
return
with language(self.locale): with language(self.locale):
recipient = self.email recipient = self.email
try: try:

View File

@@ -521,6 +521,9 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
if not pprov: if not pprov:
raise OrderError(error_messages['internal']) raise OrderError(error_messages['internal'])
if email == settings.PRETIX_EMAIL_NONE_VALUE:
email = None
addr = None addr = None
if address is not None: if address is not None:
try: try:
@@ -542,44 +545,48 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
invoice = order.invoices.last() # Might be generated by plugin already invoice = order.invoices.last() # Might be generated by plugin already
if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order):
if not invoice: if not invoice:
invoice = generate_invoice(order, trigger_pdf=not event.settings.invoice_email_attachment) invoice = generate_invoice(
order,
trigger_pdf=not event.settings.invoice_email_attachment or not order.email
)
# send_mail will trigger PDF generation later # send_mail will trigger PDF generation later
if order.payment_provider == 'free': if order.email:
email_template = event.settings.mail_text_order_free if order.payment_provider == 'free':
log_entry = 'pretix.event.order.email.order_free' email_template = event.settings.mail_text_order_free
else: log_entry = 'pretix.event.order.email.order_free'
email_template = event.settings.mail_text_order_placed else:
log_entry = 'pretix.event.order.email.order_placed' email_template = event.settings.mail_text_order_placed
log_entry = 'pretix.event.order.email.order_placed'
try: try:
invoice_name = order.invoice_address.name invoice_name = order.invoice_address.name
invoice_company = order.invoice_address.company invoice_company = order.invoice_address.company
except InvoiceAddress.DoesNotExist: except InvoiceAddress.DoesNotExist:
invoice_name = "" invoice_name = ""
invoice_company = "" invoice_company = ""
email_context = { email_context = {
'total': LazyNumber(order.total), 'total': LazyNumber(order.total),
'currency': event.currency, 'currency': event.currency,
'date': LazyDate(order.expires), 'date': LazyDate(order.expires),
'event': event.name, 'event': event.name,
'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'url': build_absolute_uri(event, 'presale:event.order', kwargs={
'order': order.code, 'order': order.code,
'secret': order.secret 'secret': order.secret
}), }),
'payment_info': str(pprov.order_pending_mail_render(order)), 'payment_info': str(pprov.order_pending_mail_render(order)),
'invoice_name': invoice_name, 'invoice_name': invoice_name,
'invoice_company': invoice_company, 'invoice_company': invoice_company,
} }
email_subject = _('Your order: %(code)s') % {'code': order.code} email_subject = _('Your order: %(code)s') % {'code': order.code}
try: try:
order.send_mail( order.send_mail(
email_subject, email_template, email_context, email_subject, email_template, email_context,
log_entry, log_entry,
invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [] invoices=[invoice] if invoice and event.settings.invoice_email_attachment else []
) )
except SendMailException: except SendMailException:
logger.exception('Order received email could not be sent') logger.exception('Order received email could not be sent')
return order.id return order.id

View File

@@ -1,3 +1,4 @@
from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@@ -11,7 +12,7 @@ class BlacklistValidator:
# Validation logic # Validation logic
if value in self.blacklist: if value in self.blacklist:
raise ValidationError( raise ValidationError(
_('This slug has an invalid value: %(value)s.'), _('This field has an invalid value: %(value)s.'),
code='invalid', code='invalid',
params={'value': value}, params={'value': value},
) )
@@ -56,3 +57,11 @@ class OrganizerSlugBlacklistValidator(BlacklistValidator):
'csp_report', 'csp_report',
'widget', 'widget',
] ]
@deconstructible
class EmailBlacklistValidator(BlacklistValidator):
blacklist = [
settings.PRETIX_EMAIL_NONE_VALUE,
]

View File

@@ -93,21 +93,23 @@
{% endif %} {% endif %}
<dt>{% trans "User" %}</dt> <dt>{% trans "User" %}</dt>
<dd> <dd>
{{ order.email }}&nbsp;&nbsp; {{ order.email|default_if_none:"" }}&nbsp;&nbsp;
<a href="{% url "control:event.order.contact" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default btn-xs"> <a href="{% url "control:event.order.contact" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default btn-xs">
<span class="fa fa-edit"></span> <span class="fa fa-edit"></span>
</a> </a>
<a href="{% url "control:event.order.sendmail" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default btn-xs"> {% if order.email %}
<span class="fa fa-envelope-o"></span> <a href="{% url "control:event.order.sendmail" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default btn-xs">
</a> <span class="fa fa-envelope-o"></span>
{% if order.status != "c" %} </a>
<form class="form-inline helper-display-inline" method="post" {% if order.status != "c" %}
action="{% url "control:event.order.resendlink" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}"> <form class="form-inline helper-display-inline" method="post"
{% csrf_token %} action="{% url "control:event.order.resendlink" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
<button class="btn btn-default btn-xs"> {% csrf_token %}
{% trans "Resend link" %} <button class="btn btn-default btn-xs">
</button> {% trans "Resend link" %}
</form> </button>
</form>
{% endif %}
{% endif %} {% endif %}
</dd> </dd>
{% if invoices %} {% if invoices %}

View File

@@ -108,7 +108,7 @@
</strong> </strong>
</td> </td>
<td> <td>
{{ o.email }} {{ o.email|default_if_none:"" }}
{% if o.invoice_address.name %} {% if o.invoice_address.name %}
<br>{{ o.invoice_address.name }} <br>{{ o.invoice_address.name }}
{% endif %} {% endif %}

View File

@@ -64,7 +64,7 @@
</td> </td>
<td>{{ o.event.name }}</td> <td>{{ o.event.name }}</td>
<td> <td>
{{ o.email }} {{ o.email|default_if_none:"" }}
{% if o.invoice_address.name %} {% if o.invoice_address.name %}
<br>{{ o.invoice_address.name }} <br>{{ o.invoice_address.name }}
{% endif %} {% endif %}

View File

@@ -60,7 +60,7 @@ class SenderView(EventPermissionRequiredMixin, FormView):
return super().form_invalid(form) return super().form_invalid(form)
def form_valid(self, form): def form_valid(self, form):
qs = Order.objects.filter(event=self.request.event) qs = Order.objects.filter(event=self.request.event, email__isnull=False)
statusq = Q(status__in=form.cleaned_data['sendto']) statusq = Q(status__in=form.cleaned_data['sendto'])
if 'overdue' in form.cleaned_data['sendto']: if 'overdue' in form.cleaned_data['sendto']:
statusq |= Q(status=Order.STATUS_PENDING, expires__lt=now()) statusq |= Q(status=Order.STATUS_PENDING, expires__lt=now())

View File

@@ -522,6 +522,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
for r, response in sorted(responses, key=lambda r: str(r[0])): for r, response in sorted(responses, key=lambda r: str(r[0])):
for key, value in response.items(): for key, value in response.items():
v = self.cart_session.get('contact_form_data', {}).get(key) v = self.cart_session.get('contact_form_data', {}).get(key)
v = value.bound_data(v, initial='')
if v is True: if v is True:
v = _('Yes') v = _('Yes')
elif v is False: elif v is False:

View File

@@ -14,6 +14,7 @@ from pretix.base.forms.questions import (
from pretix.base.models import ItemVariation from pretix.base.models import ItemVariation
from pretix.base.models.tax import TAXED_ZERO from pretix.base.models.tax import TAXED_ZERO
from pretix.base.templatetags.rich_text import rich_text from pretix.base.templatetags.rich_text import rich_text
from pretix.base.validators import EmailBlacklistValidator
from pretix.presale.signals import contact_form_fields from pretix.presale.signals import contact_form_fields
@@ -23,6 +24,7 @@ class ContactForm(forms.Form):
help_text=_('Make sure to enter a valid email address. We will send you an order ' help_text=_('Make sure to enter a valid email address. We will send you an order '
'confirmation including a link that you need in case you want to make ' 'confirmation including a link that you need in case you want to make '
'modifications to your order or download your ticket later.'), 'modifications to your order or download your ticket later.'),
validators=[EmailBlacklistValidator()],
widget=forms.EmailInput(attrs={'autofocus': 'autofocus'})) widget=forms.EmailInput(attrs={'autofocus': 'autofocus'}))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@@ -120,10 +120,12 @@
</h3> </h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<dl class="dl-horizontal"> {% if "email" not in contact_info.keys %}
<dt>{% trans "E-mail address" %}</dt> <dl class="dl-horizontal">
<dd>{{ cart_session.email }}</dd> <dt>{% trans "E-mail address" %}</dt>
</dl> <dd>{{ cart_session.email }}</dd>
</dl>
{% endif %}
{% for l, v in contact_info %} {% for l, v in contact_info %}
<dl class="dl-horizontal"> <dl class="dl-horizontal">
<dt>{{ l }}</dt> <dt>{{ l }}</dt>

View File

@@ -187,6 +187,7 @@ ENTROPY = {
} }
# Internal settings # Internal settings
PRETIX_EMAIL_NONE_VALUE = 'none@well-known.pretix.eu'
STATIC_ROOT = os.path.join(os.path.dirname(__file__), 'static.dist') STATIC_ROOT = os.path.join(os.path.dirname(__file__), 'static.dist')