mirror of
https://github.com/pretix/pretix.git
synced 2026-05-10 16:04:02 +00:00
Send e-mails on order completion (#27)
This commit is contained in:
@@ -77,6 +77,8 @@ The provider class
|
|||||||
|
|
||||||
.. automethod:: checkout_perform
|
.. automethod:: checkout_perform
|
||||||
|
|
||||||
|
.. automethod:: order_pending_mail_render
|
||||||
|
|
||||||
.. automethod:: order_pending_render
|
.. automethod:: order_pending_render
|
||||||
|
|
||||||
This is an abstract method, you **must** override this!
|
This is an abstract method, you **must** override this!
|
||||||
|
|||||||
51
src/pretix/base/mail.py
Normal file
51
src/pretix/base/mail.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import logging
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.mail import EmailMessage
|
||||||
|
from django.template.loader import get_template
|
||||||
|
from django.utils import translation
|
||||||
|
|
||||||
|
from pretix.base.models import User, Event
|
||||||
|
|
||||||
|
logger = logging.getLogger('pretix.base.mail')
|
||||||
|
|
||||||
|
|
||||||
|
def mail(user: User, subject: str, template: str, context: dict, event: Event=None):
|
||||||
|
"""
|
||||||
|
Sends out an email to a user.
|
||||||
|
|
||||||
|
:param user: The user this should be sent to.
|
||||||
|
:param subject: The e-mail subject. Should be localized.
|
||||||
|
:param template: The filename of a template to be used. It will
|
||||||
|
be rendered with the recipient's locale.
|
||||||
|
:param context: The context for rendering the template.
|
||||||
|
:param event: The event, used for determining the sender of the e-mail
|
||||||
|
|
||||||
|
:return: ``False`` on obvious failures, like the user having to e-mail
|
||||||
|
address, ``True`` otherwise. ``True`` does not necessarily mean that
|
||||||
|
the email has been sent, just that it has been queued by the e-mail
|
||||||
|
backend.
|
||||||
|
"""
|
||||||
|
if not user.email:
|
||||||
|
return False
|
||||||
|
|
||||||
|
_lng = translation.get_language()
|
||||||
|
translation.activate(user.locale or settings.LANGUAGE_CODE)
|
||||||
|
|
||||||
|
tpl = get_template(template)
|
||||||
|
body = tpl.render(context)
|
||||||
|
|
||||||
|
sender = event.settings.get('mail_from') if event else settings.MAIL_FROM
|
||||||
|
|
||||||
|
email = EmailMessage(
|
||||||
|
subject, body, sender,
|
||||||
|
to=[user.email]
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
email.send(fail_silently=False)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
logger.exception('Error sending e-mail')
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
translation.activate(_lng)
|
||||||
@@ -248,6 +248,16 @@ class BasePaymentProvider:
|
|||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def order_pending_mail_render(self, order: Order) -> str:
|
||||||
|
"""
|
||||||
|
After the user submitted his order, he or she will receive a confirmation
|
||||||
|
e-mail. You can return a string from this method if you want to add additional
|
||||||
|
information to this e-mail.
|
||||||
|
|
||||||
|
:param order: The order object
|
||||||
|
"""
|
||||||
|
return ""
|
||||||
|
|
||||||
def order_pending_render(self, request: HttpRequest, order: Order) -> str:
|
def order_pending_render(self, request: HttpRequest, order: Order) -> str:
|
||||||
"""
|
"""
|
||||||
If the user visits a detail page of an order which has not yet been paid but
|
If the user visits a detail page of an order which has not yet been paid but
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import decimal
|
|||||||
|
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
|
from django.conf import settings
|
||||||
from versions.models import Versionable
|
from versions.models import Versionable
|
||||||
|
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ DEFAULTS = {
|
|||||||
'attendee_names_required': 'False',
|
'attendee_names_required': 'False',
|
||||||
'reservation_time': '30',
|
'reservation_time': '30',
|
||||||
'last_order_modification_date': None,
|
'last_order_modification_date': None,
|
||||||
|
'mail_from': settings.MAIL_FROM,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ class BankTransfer(BasePaymentProvider):
|
|||||||
ctx = {'request': request, 'form': form, 'settings': self.settings}
|
ctx = {'request': request, 'form': form, 'settings': self.settings}
|
||||||
return template.render(ctx)
|
return template.render(ctx)
|
||||||
|
|
||||||
|
def order_pending_mail_render(self, order) -> str:
|
||||||
|
template = get_template('pretixplugins/banktransfer/email/order_pending.txt')
|
||||||
|
ctx = {'event': self.event, 'order': order, 'settings': self.settings}
|
||||||
|
return template.render(ctx)
|
||||||
|
|
||||||
def order_pending_render(self, request, order) -> str:
|
def order_pending_render(self, request, order) -> str:
|
||||||
template = get_template('pretixplugins/banktransfer/pending.html')
|
template = get_template('pretixplugins/banktransfer/pending.html')
|
||||||
ctx = {'request': request, 'order': order, 'settings': self.settings}
|
ctx = {'request': request, 'order': order, 'settings': self.settings}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{% load i18n %}{% blocktrans with bank=settings.bank_details code=order.full_code %}
|
||||||
|
Please transfer the full amount to the following bank account.
|
||||||
|
|
||||||
|
Reference: {{ code }}
|
||||||
|
{{ bank }}{% endblocktrans %}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{% load i18n %}{% blocktrans with event=event.name total=order.total|floatformat:2 currency=event.currency paymentinfo=payment date=order.expires|date url=url %}Hello,
|
||||||
|
|
||||||
|
we successfully received your order for {{ event }} with a total value
|
||||||
|
of {{ total }} {{ currency }}. Please complete your payment before {{ date }}.
|
||||||
|
{{ paymentinfo }}
|
||||||
|
|
||||||
|
You can view the status of your order at
|
||||||
|
|
||||||
|
{{ url }}
|
||||||
|
|
||||||
|
Best regards,
|
||||||
|
Your {{ event }} team
|
||||||
|
{% endblocktrans %}
|
||||||
@@ -4,11 +4,13 @@ from django.core.urlresolvers import reverse
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Q, Sum
|
from django.db.models import Q, Sum
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from pretix.base.mail import mail
|
||||||
from pretix.base.models import CartPosition, Question, QuestionAnswer, Quota, Order, OrderPosition
|
from pretix.base.models import CartPosition, Question, QuestionAnswer, Quota, Order, OrderPosition
|
||||||
from pretix.base.signals import register_payment_providers
|
from pretix.base.signals import register_payment_providers
|
||||||
|
|
||||||
@@ -319,7 +321,7 @@ class OrderConfirm(EventViewMixin, CartDisplayMixin, EventLoginRequiredMixin, Ch
|
|||||||
self.request = request
|
self.request = request
|
||||||
return self.check_process(request) or self.perform_order(request)
|
return self.check_process(request) or self.perform_order(request)
|
||||||
|
|
||||||
def perform_order(self, request):
|
def perform_order(self, request: HttpRequest):
|
||||||
dt = now()
|
dt = now()
|
||||||
quotas_locked = set()
|
quotas_locked = set()
|
||||||
|
|
||||||
@@ -362,6 +364,17 @@ class OrderConfirm(EventViewMixin, CartDisplayMixin, EventLoginRequiredMixin, Ch
|
|||||||
if not self.msg_some_unavailable: # Everything went well
|
if not self.msg_some_unavailable: # Everything went well
|
||||||
order = self._place_order(cartpos, dt)
|
order = self._place_order(cartpos, dt)
|
||||||
messages.success(request, _('Your order has been placed.'))
|
messages.success(request, _('Your order has been placed.'))
|
||||||
|
mail(
|
||||||
|
request.user, _('Your order: %(code)s') % {'code': order.code},
|
||||||
|
'pretixpresale/email/order_placed.txt',
|
||||||
|
{
|
||||||
|
'user': request.user, 'order': order,
|
||||||
|
'event': request.event,
|
||||||
|
'url': request.build_absolute_uri(self.get_order_url(order)),
|
||||||
|
'payment': self.payment_provider.order_pending_mail_render(order)
|
||||||
|
},
|
||||||
|
request.event
|
||||||
|
)
|
||||||
resp = self.payment_provider.checkout_perform(request, order)
|
resp = self.payment_provider.checkout_perform(request, order)
|
||||||
return redirect(resp or self.get_order_url(order))
|
return redirect(resp or self.get_order_url(order))
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,9 @@ LOGGING = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MAIL_FROM = 'pretix@localhost'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from local_settings import * # NOQA
|
from .local_settings import * # NOQA
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user