Compare commits

..
Author SHA1 Message Date
Richard Schreiber 0a6f80134b fix flake8 2026-08-06 14:41:28 +02:00
Richard Schreiber 2b4d93c1ec Widget: serve vite by default, origin-whitelist for vue2 2026-08-06 14:41:28 +02:00
13 changed files with 50 additions and 507 deletions
+2 -2
View File
@@ -2038,7 +2038,7 @@ Manipulating individual positions
* ``order`` (mandatory, specified as a string mapping to a ``code``)
* ``addon_to`` (optional, specified as an integer mapping to ``positionid`` - the number of the position within the order, see :ref:`_order-position-resource` - of the parent position)
* ``addon_to`` (optional, specified as an integer mapping to the ``positionid`` of the parent position)
* ``item`` (mandatory)
@@ -2348,7 +2348,7 @@ otherwise, such as splitting an order or changing fees.
"subevent": 562,
"seat": "seat-guid-2",
"price": "99.99",
"addon_to": 1,
"addon_to": 12374,
"attendee_name": "Peter",
}
],
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -105,12 +105,12 @@ class GlobalSettingsForm(SettingsForm):
domain=settings.SITE_URL
)
)),
('widget_vite_origins', forms.CharField(
('widget_vue2_origins', forms.CharField(
widget=forms.Textarea(attrs={'rows': '3'}),
required=False,
# Not translated on purpose, this is a temporary feature and contains too many special case words
label="Vite widget origins",
help_text="One origin per line (e.g. https://example.com). Requests from these origins will be served the new vite-based widget.",
label="Vue2 widget origins",
help_text="One origin per line (e.g. https://example.com). Requests from these origins will be served the old vue2-based widget.",
))
])
responses = register_global_settings.send(self)
-2
View File
@@ -677,8 +677,6 @@ class PaypalMethod(BasePaymentProvider):
raise PaymentException(_('We had trouble communicating with PayPal'))
else:
pp_captured_order = response.result
payment.info = json.dumps(pp_captured_order.dict())
payment.save()
try:
ReferencedPayPalObject.objects.get_or_create(order=payment.order, payment=payment, reference=pp_captured_order.id)
+5 -6
View File
@@ -357,13 +357,14 @@ def webhook(request, *args, **kwargs):
if 'resource_type' not in event_json:
return HttpResponse("Invalid body, no resource_type given", status=400)
if event_json['resource_type'] not in ["checkout-order", "refund", "capture"]:
return HttpResponse("Not interested in this resource type", status=200)
# Retrieve the Charge ID of the refunded payment
if event_json['resource_type'] == 'checkout-order':
payloadid = event_json['resource']['id']
elif event_json['resource_type'] == 'refund' or event_json['resource_type'] == 'capture':
if event_json['resource_type'] == 'refund':
payloadid = get_link(event_json['resource']['links'], 'up')['href'].split('/')[-1]
else:
return HttpResponse("Not interested in this resource type", status=200)
payloadid = event_json['resource']['id']
refs = [payloadid]
if event_json['resource'].get('supplementary_data', {}).get('related_ids', {}).get('order_id'):
@@ -423,8 +424,6 @@ def webhook(request, *args, **kwargs):
**event_json,
'_order_state': sale.dict(),
})
payment.info = json.dumps(sale.dict())
payment.save()
if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED and sale['status'] in ('PARTIALLY_REFUNDED', 'REFUNDED', 'COMPLETED'):
if event_json['resource_type'] == 'refund':
+1 -11
View File
@@ -158,12 +158,7 @@ class OrderMailForm(BaseMailForm):
),
label=pgettext_lazy('sendmail_form', 'Restrict to products'),
required=True,
queryset=Item.objects.none(),
help_text=pgettext_lazy(
'sendmail_form',
'There may be multiple mails sent out to the same mail address if one order contains multiple attendee '
'products for it, if you restrict to products while also restricting mails to attendees only. '
'This is intended, as every one of those get linked to their own separate order page restricted to only that product.')
queryset=Item.objects.none()
)
filter_checkins = forms.BooleanField(
label=_('Filter check-in status'),
@@ -376,11 +371,6 @@ class RuleForm(FormPlaceholderMixin, I18nModelForm):
del self.fields['subevent']
self.fields['limit_products'].queryset = Item.objects.filter(event=self.event)
self.fields['limit_products'].help_text = pgettext_lazy(
'sendmail_form',
'There may be multiple mails sent out to the same mail address if one order contains multiple attendee '
'products for it, if you restrict to products while also restricting mails to attendees only. '
'This is intended, as every one of those get linked to their own separate order page restricted to only that product.')
self.fields['schedule_type'] = forms.ChoiceField(
label=_('Type of schedule time'),
+2 -22
View File
@@ -187,32 +187,13 @@ class ScheduledMail(models.Model):
o_sent = True
if send_to_attendees:
if not self.rule.all_products:
positions = [p for p in positions if p.item_id in limit_products]
if self.subevent_id:
positions = [p for p in positions if p.subevent_id == self.subevent_id]
parent_op = None
sent_to_positions = set()
for p in positions:
if p.addon_to_id is None:
parent_op = p
if not self.rule.all_products and p.id not in position_ids:
continue
if p.id in position_ids:
if p.addon_to_id:
if not parent_op or parent_op.id != p.addon_to_id:
# something got mixed up with this order as addons should always come after their parent-position
continue
if not p.attendee_email:
if p.addon_to_id in sent_to_positions:
continue
else:
p = parent_op
# with attendee-email but same as parent's and sent to parent
elif parent_op.attendee_email and p.attendee_email == parent_op.attendee_email and parent_op.pk in sent_to_positions:
continue
if p.attendee_email and (p.attendee_email != o.email or not o_sent):
email_ctx = get_email_context(
event=e,
@@ -224,7 +205,6 @@ class ScheduledMail(models.Model):
p.send_mail(self.rule.subject, self.rule.template, email_ctx,
attach_ical=self.rule.attach_ical,
log_entry_type='pretix.plugins.sendmail.rule.order.position.email.sent')
sent_to_positions.add(p.id)
elif not o_sent and o.email:
email_ctx = get_email_context(
event=e,
+24 -66
View File
@@ -70,8 +70,6 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
except InvoiceAddress.DoesNotExist:
ia = InvoiceAddress(order=o)
parent_op = None
sent_to_positions = set()
if recipients in ('both', 'attendees'):
for p in o.positions.annotate(
any_checkins=Exists(
@@ -87,13 +85,10 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
)
),
).prefetch_related('addons', 'subevent'):
if p.addon_to_id is not None:
continue
is_addon = p.addon_to_id is not None
if not is_addon:
parent_op = p
if p.item_id not in items:
if p.item_id not in items and not any(a.item_id in items for a in p.addons.all()):
continue
if filter_checkins:
@@ -104,25 +99,12 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
if not allowed:
continue
send_to_parent = False
if not p.attendee_email:
if recipients == 'attendees':
if is_addon:
if p.addon_to_id in sent_to_positions:
continue
elif parent_op and parent_op.id == p.addon_to_id and parent_op.attendee_email:
send_to_parent = True
else:
send_to_order = True
continue
else:
send_to_order = True
continue
# add-on's attendee-email is the same as parent's and sent to parent
elif is_addon and p.addon_to_id in sent_to_positions and p.attendee_email == parent_op.attendee_email:
send_to_order = True
continue
if p.attendee_email and p.attendee_email == o.email and send_to_order:
if p.attendee_email == o.email and send_to_order:
continue
if subevent and p.subevent_id != subevent:
@@ -135,50 +117,26 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
continue
with language(o.locale, event.settings.region):
if send_to_parent:
email_context = get_email_context(event=event, order=o, invoice_address=ia, position=parent_op)
outgoing_mail = mail(
parent_op.attendee_email,
subject,
message,
email_context,
event,
locale=o.locale,
order=o,
position=parent_op,
attach_tickets=attach_tickets,
attach_ical=attach_ical,
attach_cached_files=attachments
email_context = get_email_context(event=event, order=o, invoice_address=ia, position=p)
outgoing_mail = mail(
p.attendee_email,
subject,
message,
email_context,
event,
locale=o.locale,
order=o,
position=p,
attach_tickets=attach_tickets,
attach_ical=attach_ical,
attach_cached_files=attachments
)
if outgoing_mail:
o.log_action(
'pretix.plugins.sendmail.order.email.sent.attendee',
user=user,
data=outgoing_mail.log_data(),
)
if outgoing_mail:
o.log_action(
'pretix.plugins.sendmail.order.email.sent.attendee',
user=user,
data=outgoing_mail.log_data(),
)
sent_to_positions.add(parent_op.id)
else:
email_context = get_email_context(event=event, order=o, invoice_address=ia, position=p)
outgoing_mail = mail(
p.attendee_email,
subject,
message,
email_context,
event,
locale=o.locale,
order=o,
position=p,
attach_tickets=attach_tickets,
attach_ical=attach_ical,
attach_cached_files=attachments
)
if outgoing_mail:
o.log_action(
'pretix.plugins.sendmail.order.email.sent.attendee',
user=user,
data=outgoing_mail.log_data(),
)
sent_to_positions.add(p.id)
if send_to_order and o.email:
with language(o.locale, event.settings.region):
+1
View File
@@ -174,6 +174,7 @@ class OrderPositionDetailMixin(NoSearchIndexViewMixin):
def position(self):
qs = OrderPosition.objects.filter(
order__event=self.request.event,
addon_to__isnull=True,
order__code=self.kwargs['order'],
positionid=self.kwargs['position']
).select_related('order', 'order__event')
+9 -8
View File
@@ -122,19 +122,20 @@ def widget_css_etag(request, version, **kwargs):
return f'{_get_source_cache_key(version)}-{request.organizer.cache.get_or_set("css_version", default=lambda: int(time.time()))}'
# use vite by default, serve old vue2-based widget only for widget_vue2_origins
def _use_vite(request):
if getattr(settings, 'PRETIX_WIDGET_VITE', False) or "beta" in request.GET:
return True
if getattr(settings, 'PRETIX_WIDGET_VUE', False) or "legacy" in request.GET:
return False
origin = request.META.get('HTTP_ORIGIN', '')
gs = GlobalSettingsObject()
vite_origins = gs.settings.get('widget_vite_origins', as_type=str, default='')
if vite_origins and not origin:
vue_origins = gs.settings.get('widget_vue2_origins', as_type=str, default='')
if vue_origins and not origin:
referer = request.META.get('HTTP_REFERER', '')
origin = '/'.join(referer.split('/', 3)[:3])
if origin and vite_origins:
origins_list = [o.strip() for o in vite_origins.strip().splitlines() if o.strip()]
return origin in origins_list
return False
if origin and vue_origins:
origins_list = [o.strip() for o in vue_origins.strip().splitlines() if o.strip()]
return origin not in origins_list
return True
def widget_js_etag(request, version, lang, **kwargs):
+2 -4
View File
@@ -22,7 +22,6 @@
import json
from datetime import timedelta
from decimal import Decimal
from unittest.mock import MagicMock
import pytest
from django.utils.timezone import now
@@ -410,8 +409,7 @@ def test_webhook_mark_paid(env, client, monkeypatch):
order.payments.update(state=OrderPayment.PAYMENT_STATE_PENDING)
pp_order = Result(get_test_order())
mock_orders_get_request = MagicMock(return_value=pp_order)
monkeypatch.setattr("paypalcheckoutsdk.orders.OrdersGetRequest", mock_orders_get_request)
monkeypatch.setattr("paypalcheckoutsdk.orders.OrdersGetRequest", lambda *args: pp_order)
monkeypatch.setattr("pretix.plugins.paypal2.payment.PaypalMethod.init_api", init_api)
with scopes_disabled():
ReferencedPayPalObject.objects.create(order=order, payment=order.payments.first(),
@@ -499,7 +497,7 @@ def test_webhook_mark_paid(env, client, monkeypatch):
"resource_version": "2.0"
}
), content_type='application_json')
mock_orders_get_request.assert_called_once_with('806440346Y391300T')
order.refresh_from_db()
assert order.status == Order.STATUS_PAID
-76
View File
@@ -197,82 +197,6 @@ def test_sendmail_rule_send_order_vs_pos(send_to, amount_mails, recipients, orde
assert set(recipients) == set(_recipients)
@pytest.mark.django_db
@pytest.mark.parametrize('send_to,amount_mails,recipients,ticket_mail,addon_mail, products', [
(Rule.ATTENDEES, 1, ['addon-attendee@dummy.test'], 'attendee@dummy.test', 'addon-attendee@dummy.test', 'addon'),
(Rule.ATTENDEES, 2, ['attendee@dummy.test', 'addon-attendee@dummy.test'], 'attendee@dummy.test',
'addon-attendee@dummy.test', 'both'),
(Rule.ATTENDEES, 1, ['attendee@dummy.test'], 'attendee@dummy.test', 'attendee@dummy.test', 'both'),
(Rule.ATTENDEES, 1, ['attendee@dummy.test'], 'attendee@dummy.test', None, 'addon'),
(Rule.ATTENDEES, 1, ['attendee@dummy.test'], 'attendee@dummy.test', None, 'both'),
(Rule.ATTENDEES, 1, ['dummy@dummy.test'], None, None, 'addon'),
(Rule.ATTENDEES, 1, ['dummy@dummy.test'], None, None, 'both'),
(Rule.ATTENDEES, 2, ['dummy@dummy.test', 'addon-attendee@dummy.test'], None, 'addon-attendee@dummy.test', 'both'),
])
@scopes_disabled()
def test_sendmail_rule_send_addons(send_to, amount_mails, recipients, ticket_mail, addon_mail, products, order,
event, pos, item, item2):
djmail.outbox = []
order.status = order.STATUS_PAID
order.save()
p = pos
p.attendee_email = ticket_mail
p.save()
order.all_positions.create(item=item2, price=0, attendee_email=addon_mail, addon_to=p)
rule = order.event.sendmail_rules.create(date_is_absolute=True, send_date=dt_now - datetime.timedelta(hours=1),
send_to=send_to, subject='meow', template='meow meow meow',
all_products=False)
if products == 'addon':
rule.limit_products.set([item2])
if products == 'both':
rule.limit_products.set([item, item2])
sendmail_run_rules(None)
assert len(djmail.outbox) == amount_mails
_recipients = [mail.to[0] for mail in djmail.outbox]
assert set(recipients) == set(_recipients)
@pytest.mark.django_db
@pytest.mark.parametrize('send_to,amount_mails,recipients,ticket_mail,addon_mail, products', [
(Rule.ATTENDEES, 2, ['attendee@dummy.test', 'addon-attendee@dummy.test'], 'attendee@dummy.test',
'addon-attendee@dummy.test', 'addon'),
(Rule.ATTENDEES, 2, ['attendee@dummy.test', 'addon-attendee@dummy.test'], 'attendee@dummy.test',
'addon-attendee@dummy.test', 'both'),
])
@scopes_disabled()
def test_sendmail_rule_send_addons_one_unp(send_to, amount_mails, recipients, ticket_mail, addon_mail, products, order,
event, pos, item, item2):
djmail.outbox = []
order.status = order.STATUS_PAID
order.save()
p = pos
p.attendee_email = ticket_mail
p.save()
order.all_positions.create(item=item2, price=0, attendee_email=addon_mail, addon_to=p)
order.all_positions.create(item=item2, price=0, addon_to=p)
rule = order.event.sendmail_rules.create(date_is_absolute=True, send_date=dt_now - datetime.timedelta(hours=1),
send_to=send_to, subject='meow', template='meow meow meow',
all_products=False)
if products == 'addon':
rule.limit_products.set([item2])
if products == 'both':
rule.limit_products.set([item, item2])
sendmail_run_rules(None)
assert len(djmail.outbox) == amount_mails
_recipients = [mail.to[0] for mail in djmail.outbox]
assert set(recipients) == set(_recipients)
@pytest.mark.django_db
@scopes_disabled()
def test_sendmail_rule_send_attendees_unset_mail(order, event, item):
-306
View File
@@ -406,312 +406,6 @@ def test_sendmail_attendee_product_filter(logged_in_client, sendmail_url, event,
assert '/order/' not in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_addon_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
order.positions.create(
item=addon, price=0, attendee_email='add-on-attendee@dummy.test', addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': addon.pk,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == ['add-on-attendee@dummy.test']
assert '/ticket/' in djmail.outbox[0].body
assert '/order/' not in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_ticket_and_addon_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
order.positions.create(
item=addon, price=0, attendee_email='add-on-attendee@dummy.test', addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, p.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 2
for msg in djmail.outbox:
assert msg.to in [['attendee1@dummy.test'], ['add-on-attendee@dummy.test']]
assert '/ticket/' in msg.body
assert '/order/' not in msg.body
@pytest.mark.django_db
def test_sendmail_attendee_ticket_and_same_addon_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
order.positions.create(
item=addon, price=0, attendee_email='attendee1@dummy.test', addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, p.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == ['attendee1@dummy.test']
assert '/ticket/' in djmail.outbox[0].body
assert '/order/' not in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_addon_unpersonalized_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
order.positions.create(
item=addon, price=0, addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': addon.pk,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == ['attendee1@dummy.test']
assert '/ticket/' in djmail.outbox[0].body
assert '/order/' not in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_ticket_and_addon_unp_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
order.positions.create(
item=addon, price=0, addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, p.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == ['attendee1@dummy.test']
assert '/ticket/' in djmail.outbox[0].body
assert '/order/' not in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_ticket_unp_and_addon_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
order.positions.create(
item=addon, price=0, attendee_email='add-on-attendee@dummy.test', addon_to=pos
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, pos.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 2
for msg in djmail.outbox:
assert msg.to in [[order.email], ['add-on-attendee@dummy.test']]
if msg.to == [order.email]:
assert '/ticket/' not in msg.body
assert '/order/' in msg.body
else:
assert msg.to == ['add-on-attendee@dummy.test']
assert '/ticket/' in msg.body
assert '/order/' not in msg.body
@pytest.mark.django_db
def test_sendmail_attendee_addon_unp_unp_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
order.positions.create(
item=addon, price=0, addon_to=pos
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': addon.pk,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [order.email]
assert '/ticket/' not in djmail.outbox[0].body
assert '/order/' in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_and_addon_unp_unp_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
order.positions.create(
item=addon, price=0, addon_to=pos
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, pos.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [order.email]
assert '/ticket/' not in djmail.outbox[0].body
assert '/order/' in djmail.outbox[0].body
@pytest.mark.django_db
def test_sendmail_attendee_two_addons_one_unp_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
order.positions.create(
item=addon, price=0, attendee_email='add-on-attendee@dummy.test', addon_to=p
)
order.positions.create(
item=addon, price=0, addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': addon.pk,
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 2
for msg in djmail.outbox:
assert msg.to in [['attendee1@dummy.test'], ['add-on-attendee@dummy.test']]
assert '/ticket/' in msg.body
assert '/order/' not in msg.body
@pytest.mark.django_db
def test_sendmail_attendee_and_two_addons_one_unp_filter(logged_in_client, sendmail_url, event, order, pos):
event.settings.attendee_emails_asked = True
with scopes_disabled():
p = pos
p.attendee_email = 'attendee1@dummy.test'
p.save()
addon = Item.objects.create(name='Test addon', event=event, default_price=12)
order.positions.create(
item=addon, price=0, attendee_email='add-on-attendee@dummy.test', addon_to=p
)
order.positions.create(
item=addon, price=0, addon_to=p
)
djmail.outbox = []
response = logged_in_client.post(sendmail_url + 'orders/',
{'sendto': 'na',
'action': 'send',
'recipients': 'attendees',
'items': {addon.pk, p.item_id},
'subject_0': 'Test subject',
'message_0': 'This is a test file for sending mails.',
},
follow=True)
assert response.status_code == 200
assert 'alert-success' in response.rendered_content
assert len(djmail.outbox) == 2
for msg in djmail.outbox:
assert msg.to in [['attendee1@dummy.test'], ['add-on-attendee@dummy.test']]
assert '/ticket/' in msg.body
assert '/order/' not in msg.body
@pytest.mark.django_db
def test_sendmail_attendee_subevent_filter(logged_in_client, sendmail_url, event, item, order, pos):
event.settings.attendee_emails_asked = True