Do not allow initiating stripe/paypal payments after the last payment

date
This commit is contained in:
Raphael Michel
2016-12-23 13:29:41 +01:00
parent 16ab6e44f5
commit d698313f1d
6 changed files with 37 additions and 14 deletions

View File

@@ -1,4 +1,5 @@
import uuid import uuid
from datetime import date, datetime, time
import pytz import pytz
from django.conf import settings from django.conf import settings
@@ -8,7 +9,7 @@ from django.core.validators import RegexValidator
from django.db import models from django.db import models
from django.template.defaultfilters import date as _date from django.template.defaultfilters import date as _date
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 make_aware, now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.email import CustomSMTPBackend from pretix.base.email import CustomSMTPBackend
@@ -208,6 +209,14 @@ class Event(LoggedModel):
else: else:
return get_connection(fail_silently=False) return get_connection(fail_silently=False)
@property
def payment_term_last(self):
tz = pytz.timezone(self.settings.timezone)
return make_aware(datetime.combine(
self.settings.get('payment_term_last', as_type=date),
time(hour=23, minute=59, second=59)
), tz)
class EventPermission(models.Model): class EventPermission(models.Model):
""" """

View File

@@ -1,17 +1,16 @@
import copy import copy
import string import string
from datetime import date, datetime, time from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import List, Union from typing import List, Union
import pytz
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from django.db.models import F from django.db.models import F
from django.db.models.signals import post_delete from django.db.models.signals import post_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.utils.timezone import make_aware, now from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from ..decimal import round_decimal from ..decimal import round_decimal
@@ -273,13 +272,7 @@ class Order(LoggedModel):
} }
if self.event.settings.get('payment_term_last'): if self.event.settings.get('payment_term_last'):
tz = pytz.timezone(self.event.settings.timezone) if now() > self.event.payment_term_last:
last_date = make_aware(datetime.combine(
self.event.settings.get('payment_term_last', as_type=date),
time(hour=23, minute=59, second=59)
), tz)
if now() > last_date:
return error_messages['late'] return error_messages['late']
if self.status == self.STATUS_PENDING: if self.status == self.STATUS_PENDING:
return True return True

View File

@@ -365,8 +365,12 @@ class BasePaymentProvider:
whether the user should be presented with an option to retry the payment. The default whether the user should be presented with an option to retry the payment. The default
implementation always returns False. implementation always returns False.
If you want to enable retrials for your payment method, the best is to just return
``self._is_still_available()`` from this method to disable it as soon as the method
gets disabled or the methods end date is reached.
The retry workflow is also used if a user switches to this payment method for an existing The retry workflow is also used if a user switches to this payment method for an existing
order! Therefore, they can only switch to your p order!
:param order: The order object :param order: The order object
""" """

View File

@@ -257,7 +257,7 @@ class Paypal(BasePaymentProvider):
order.save() order.save()
def order_can_retry(self, order): def order_can_retry(self, order):
return True return self._is_still_available()
def order_prepare(self, request, order): def order_prepare(self, request, order):
self.init_api() self.init_api()

View File

@@ -86,7 +86,7 @@ class Stripe(BasePaymentProvider):
return template.render(ctx) return template.render(ctx)
def order_can_retry(self, order): def order_can_retry(self, order):
return True return self._is_still_available()
def payment_perform(self, request, order) -> str: def payment_perform(self, request, order) -> str:
self._init_api() self._init_api()

View File

@@ -139,6 +139,11 @@ class OrderPaymentStart(EventViewMixin, OrderDetailMixin, TemplateView):
or not self.payment_provider.is_enabled): or not self.payment_provider.is_enabled):
messages.error(request, _('The payment for this order cannot be continued.')) messages.error(request, _('The payment for this order cannot be continued.'))
return redirect(self.get_order_url()) return redirect(self.get_order_url())
if self.request.event.settings.get('payment_term_last'):
if now() > self.request.event.payment_term_last:
messages.error(request, _('The payment is too late to be accepted.'))
return redirect(self.get_order_url())
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@@ -225,6 +230,12 @@ class OrderPaymentComplete(EventViewMixin, OrderDetailMixin, View):
not self.payment_provider.is_enabled): not self.payment_provider.is_enabled):
messages.error(request, _('The payment information you entered was incomplete.')) messages.error(request, _('The payment information you entered was incomplete.'))
return redirect(self.get_payment_url()) return redirect(self.get_payment_url())
if self.request.event.settings.get('payment_term_last'):
if now() > self.request.event.payment_term_last:
messages.error(request, _('The payment is too late to be accepted.'))
return redirect(self.get_order_url())
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@@ -251,6 +262,12 @@ class OrderPayChangeMethod(EventViewMixin, OrderDetailMixin, TemplateView):
if self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): if self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED):
messages.error(request, _('The payment method for this order cannot be changed.')) messages.error(request, _('The payment method for this order cannot be changed.'))
return redirect(self.get_order_url()) return redirect(self.get_order_url())
if self.request.event.settings.get('payment_term_last'):
if now() > self.request.event.payment_term_last:
messages.error(request, _('The payment is too late to be accepted.'))
return redirect(self.get_order_url())
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_payment_url(self): def get_payment_url(self):