Order approval: Add attendee mail settings (Z#23114617, Z#23118978) (#3234)

Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
Phin Wolkwitz
2023-04-24 13:31:03 +02:00
committed by GitHub
parent 4fc6593b60
commit 73776ce0dd
5 changed files with 159 additions and 2 deletions

View File

@@ -391,9 +391,15 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None, force=False
if order.total == Decimal('0.00'):
email_template = order.event.settings.mail_text_order_approved_free
email_subject = order.event.settings.mail_subject_order_approved_free
email_attendees = order.event.settings.mail_send_order_approved_free_attendee
email_attendee_template = order.event.settings.mail_text_order_approved_free_attendee
email_attendee_subject = order.event.settings.mail_subject_order_approved_free_attendee
else:
email_template = order.event.settings.mail_text_order_approved
email_subject = order.event.settings.mail_subject_order_approved
email_attendees = order.event.settings.mail_send_order_approved_attendee
email_attendee_template = order.event.settings.mail_text_order_approved_attendee
email_attendee_subject = order.event.settings.mail_subject_order_approved_attendee
email_context = get_email_context(event=order.event, order=order)
try:
@@ -406,6 +412,19 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None, force=False
except SendMailException:
logger.exception('Order approved email could not be sent')
if email_attendees:
for p in order.positions.all():
if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
email_attendee_context = get_email_context(event=order.event, order=order, position=p)
try:
p.send_mail(
email_attendee_subject, email_attendee_template, email_attendee_context,
'pretix.event.order.email.order_approved', user,
attach_tickets=True,
)
except SendMailException:
logger.exception('Order approved email could not be sent to attendee')
return order.pk

View File

@@ -2275,6 +2275,26 @@ You can select a payment method and perform the payment here:
{url}
Best regards,
Your {event} team"""))
},
'mail_send_order_approved_attendee': {
'type': bool,
'default': 'False'
},
'mail_subject_order_approved_attendee': {
'type': LazyI18nString,
'default': LazyI18nString.from_gettext(gettext_noop("Your event registration: {code}")),
},
'mail_text_order_approved_attendee': {
'type': LazyI18nString,
'default': LazyI18nString.from_gettext(gettext_noop("""Hello,
we approved a ticket ordered for you for {event}.
You can view the details and status of your ticket here:
{url}
Best regards,
Your {event} team"""))
},
@@ -2292,6 +2312,26 @@ at our event. As you only ordered free products, no payment is required.
You can change your order details and view the status of your order at
{url}
Best regards,
Your {event} team"""))
},
'mail_send_order_approved_free_attendee': {
'type': bool,
'default': 'False'
},
'mail_subject_order_approved_free_attendee': {
'type': LazyI18nString,
'default': LazyI18nString.from_gettext(gettext_noop("Your event registration: {code}")),
},
'mail_text_order_approved_free_attendee': {
'type': LazyI18nString,
'default': LazyI18nString.from_gettext(gettext_noop("""Hello,
we approved a ticket ordered for you for {event}.
You can view the details and status of your ticket here:
{url}
Best regards,
Your {event} team"""))
},

View File

@@ -1191,6 +1191,24 @@ class MailSettingsForm(SettingsForm):
help_text=_("This will only be sent out for non-free orders. Free orders will receive the free order "
"template from below instead."),
)
mail_send_order_approved_attendee = forms.BooleanField(
label=_("Send an email to attendees"),
help_text=_('If the order contains attendees with email addresses different from the person who orders the '
'tickets, the following email will be sent out to the attendees.'),
required=False,
)
mail_subject_order_approved_attendee = I18nFormField(
label=_("Subject sent to attendees"),
required=False,
widget=I18nTextInput,
)
mail_text_order_approved_attendee = I18nFormField(
label=_("Text sent to attendees"),
required=False,
widget=I18nTextarea,
help_text=_("This will only be sent out for non-free orders. Free orders will receive the free order "
"template from below instead."),
)
mail_subject_order_approved_free = I18nFormField(
label=_("Subject for approved free order"),
required=False,
@@ -1203,6 +1221,24 @@ class MailSettingsForm(SettingsForm):
help_text=_("This will only be sent out for free orders. Non-free orders will receive the non-free order "
"template from above instead."),
)
mail_send_order_approved_free_attendee = forms.BooleanField(
label=_("Send an email to attendees"),
help_text=_('If the order contains attendees with email addresses different from the person who orders the '
'tickets, the following email will be sent out to the attendees.'),
required=False,
)
mail_subject_order_approved_free_attendee = I18nFormField(
label=_("Subject sent to attendees"),
required=False,
widget=I18nTextInput,
)
mail_text_order_approved_free_attendee = I18nFormField(
label=_("Text sent to attendees"),
required=False,
widget=I18nTextarea,
help_text=_("This will only be sent out for free orders. Non-free orders will receive the non-free order "
"template from above instead."),
)
mail_subject_order_denied = I18nFormField(
label=_("Subject for denied order"),
required=False,

View File

@@ -118,7 +118,7 @@
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="ticket_reminder" title=title_download_tickets_reminder items="mail_days_download_reminder,mail_subject_download_reminder,mail_text_download_reminder,mail_send_download_reminder_attendee,mail_subject_download_reminder_attendee,mail_text_download_reminder_attendee,mail_sales_channel_download_reminder" exclude="mail_days_download_reminder,mail_send_download_reminder_attendee,mail_sales_channel_download_reminder" %}
{% blocktrans asvar title_require_approval %}Order approval process{% endblocktrans %}
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="ticket_reminder" title=title_require_approval items="mail_subject_order_placed_require_approval,mail_text_order_placed_require_approval,mail_subject_order_approved,mail_text_order_approved,mail_subject_order_approved_free,mail_text_order_approved_free,mail_subject_order_denied,mail_text_order_denied" %}
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="ticket_reminder" title=title_require_approval items="mail_subject_order_placed_require_approval,mail_text_order_placed_require_approval,mail_subject_order_approved,mail_text_order_approved,mail_send_order_approved_attendee,mail_subject_order_approved_attendee,mail_text_order_approved_attendee,mail_subject_order_approved_free,mail_text_order_approved_free,mail_send_order_approved_free_attendee,mail_subject_order_approved_free_attendee,mail_text_order_approved_free_attendee,mail_subject_order_denied,mail_text_order_denied" exclude="mail_send_order_approved_attendee,mail_send_order_approved_free_attendee"%}
</div>
<h4>{% trans "Attachments" %}</h4>
{% bootstrap_field form.mail_attachment_new_order layout="control" %}

View File

@@ -454,12 +454,42 @@ def test_approve(event):
assert o1.invoices.count() == 1
assert len(djmail.outbox) == 1
assert 'awaiting payment' in djmail.outbox[0].subject
assert djmail.outbox[0].to == ['dummy@dummy.test']
@pytest.mark.django_db
def test_approve_send_to_attendees(event):
djmail.outbox = []
event.settings.invoice_generate = True
event.settings.mail_send_order_approved_attendee = True
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=10, require_approval=True, locale='en'
)
ticket = Item.objects.create(event=event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
OrderPosition.objects.create(
order=o1, item=ticket, variation=None, price=Decimal("23.00"),
attendee_name_parts={'full_name': "Peter"}, attendee_email='attendee@dummy.test',
positionid=1
)
o1.create_transactions()
assert o1.transactions.count() == 0
approve_order(o1)
o1.refresh_from_db()
assert len(djmail.outbox) == 2
assert djmail.outbox[0].to == ['dummy@dummy.test']
assert djmail.outbox[1].to == ['attendee@dummy.test']
assert 'awaiting payment' in djmail.outbox[0].subject
assert 'awaiting payment' not in djmail.outbox[1].subject
@pytest.mark.django_db
def test_approve_free(event):
djmail.outbox = []
event.settings.invoice_generate = 'True'
event.settings.invoice_generate = True
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
@@ -474,6 +504,38 @@ def test_approve_free(event):
assert o1.invoices.count() == 0
assert len(djmail.outbox) == 1
assert 'confirmed' in djmail.outbox[0].subject
assert djmail.outbox[0].to == ['dummy@dummy.test']
@pytest.mark.django_db
def test_approve_free_send_to_attendees(event):
djmail.outbox = []
event.settings.invoice_generate = True
event.settings.mail_send_order_approved_free_attendee = True
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=0, require_approval=True
)
ticket = Item.objects.create(event=event, name='Free ticket',
default_price=Decimal('0.00'), admission=True)
OrderPosition.objects.create(
order=o1, item=ticket, variation=None, price=Decimal("0.00"),
attendee_name_parts={'full_name': "Peter"}, attendee_email='attendee@dummy.test',
positionid=1
)
approve_order(o1)
o1.refresh_from_db()
assert o1.expires > now()
assert o1.status == Order.STATUS_PAID
assert not o1.require_approval
assert o1.invoices.count() == 0
assert len(djmail.outbox) == 2
assert djmail.outbox[0].to == ['dummy@dummy.test']
assert djmail.outbox[1].to == ['attendee@dummy.test']
assert 'confirmed' in djmail.outbox[0].subject
assert 'registration' in djmail.outbox[1].subject
@pytest.mark.django_db