forked from CGM_Public/pretix_original
Add support for orders without email addresses
This commit is contained in:
@@ -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")
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
]
|
||||||
|
|||||||
@@ -93,21 +93,23 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<dt>{% trans "User" %}</dt>
|
<dt>{% trans "User" %}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{ order.email }}
|
{{ order.email|default_if_none:"" }}
|
||||||
<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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user