Payment: Add setting to prevent reminder mails (Z#23123914) (#3573)

Adds a checkbox in each payment provider's settings controlling whether sending out expiry reminders should be prevented
This commit is contained in:
Phin Wolkwitz
2023-09-07 14:27:09 +02:00
committed by GitHub
parent f97e6d0a71
commit 3f07050d42
3 changed files with 76 additions and 2 deletions

View File

@@ -441,6 +441,13 @@ class BasePaymentProvider:
'Share this link with customers who should use this payment method.'
),
)),
('_prevent_reminder_mail',
forms.BooleanField(
label=_('Do not send a payment reminder mail'),
help_text=_('Users will not receive a reminder mail to pay for their order before it expires if '
'they have chosen this payment method.'),
required=False,
)),
])
d['_restricted_countries']._as_type = list
d['_restrict_to_sales_channels']._as_type = list
@@ -497,6 +504,14 @@ class BasePaymentProvider:
if order.status == Order.STATUS_PAID:
return _('paid')
def prevent_reminder_mail(self, order: Order, payment: OrderPayment) -> bool:
"""
This is called when a periodic task runs and sends out reminder mails to orders that have not been paid yet
and are soon expiring.
The default implementation returns the content of the _prevent_reminder_mail configuration variable (a boolean value).
"""
return self.settings.get('_prevent_reminder_mail', as_type=bool, default=False)
@property
def payment_form_fields(self) -> dict:
"""

View File

@@ -1289,9 +1289,18 @@ def send_expiry_warnings(sender, **kwargs):
event_id = None
for o in Order.objects.filter(
expires__gte=today, expiry_reminder_sent=False, status=Order.STATUS_PENDING,
datetime__lte=now() - timedelta(hours=2), require_approval=False
expires__gte=today, expiry_reminder_sent=False, status=Order.STATUS_PENDING,
datetime__lte=now() - timedelta(hours=2), require_approval=False
).only('pk', 'event_id', 'expires').order_by('event_id'):
lp = o.payments.last()
if (
lp and
lp.state in [OrderPayment.PAYMENT_STATE_CREATED, OrderPayment.PAYMENT_STATE_PENDING] and
lp.payment_provider.prevent_reminder_mail(o, lp)
):
continue
if event_id != o.event_id:
settings = o.event.settings
days = cache.get_or_set('{}:{}:setting_mail_days_order_expire_warning'.format('event', o.event_id),

View File

@@ -683,6 +683,56 @@ class PaymentReminderTests(TestCase):
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_prevent_reminder_mail(self):
self.event.settings.mail_days_order_expire_warning = 12
pprov = list(self.event.get_payment_providers().keys())[0]
for state in [
OrderPayment.PAYMENT_STATE_PENDING,
OrderPayment.PAYMENT_STATE_CREATED,
]:
payment = self.order.payments.create(
state=state,
amount=self.order.total,
provider=pprov
)
payment.payment_provider.settings.set('_prevent_reminder_mail', True)
payment.save()
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_prevent_reminder_mail_failed_state(self):
self.event.settings.mail_days_order_expire_warning = 12
pprov = list(self.event.get_payment_providers().keys())[0]
payment = self.order.payments.create(
state=OrderPayment.PAYMENT_STATE_CREATED,
amount=self.order.total,
provider=pprov
)
payment.payment_provider.settings.set('_prevent_reminder_mail', True)
payment.save()
payment.fail()
djmail.outbox = []
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_prevent_reminder_mail_confirmed_but_not_all_paid(self):
self.event.settings.mail_days_order_expire_warning = 12
pprov = list(self.event.get_payment_providers().keys())[0]
payment = self.order.payments.create(
state=OrderPayment.PAYMENT_STATE_CREATED,
amount=self.order.total / 2,
provider=pprov
)
payment.payment_provider.settings.set('_prevent_reminder_mail', True)
payment.save()
payment.confirm()
djmail.outbox = []
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_paid(self):
self.order.status = Order.STATUS_PAID