Fix #522 -- Do not allow any orders after the last date of payments

This commit is contained in:
Raphael Michel
2019-04-23 09:46:34 +02:00
parent 45a6923220
commit 02e936ee7a
2 changed files with 58 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
from collections import Counter, defaultdict, namedtuple from collections import Counter, defaultdict, namedtuple
from datetime import timedelta from datetime import datetime, time, timedelta
from decimal import Decimal from decimal import Decimal
from typing import List, Optional from typing import List, Optional
@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
from django.db import transaction from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.timezone import now from django.utils.timezone import make_aware, now
from django.utils.translation import pgettext_lazy, ugettext as _ from django.utils.translation import pgettext_lazy, ugettext as _
from pretix.base.i18n import language from pretix.base.i18n import language
@@ -19,6 +19,7 @@ from pretix.base.models import (
from pretix.base.models.event import SubEvent from pretix.base.models.event import SubEvent
from pretix.base.models.orders import OrderFee from pretix.base.models.orders import OrderFee
from pretix.base.models.tax import TAXED_ZERO, TaxedPrice, TaxRule from pretix.base.models.tax import TAXED_ZERO, TaxedPrice, TaxRule
from pretix.base.reldate import RelativeDateWrapper
from pretix.base.services.checkin import _save_answers from pretix.base.services.checkin import _save_answers
from pretix.base.services.locking import LockTimeoutException from pretix.base.services.locking import LockTimeoutException
from pretix.base.services.pricing import get_price from pretix.base.services.pricing import get_price
@@ -134,6 +135,15 @@ class CartManager:
raise CartError(error_messages['not_started']) raise CartError(error_messages['not_started'])
if self.event.presale_has_ended: if self.event.presale_has_ended:
raise CartError(error_messages['ended']) raise CartError(error_messages['ended'])
if not self.event.has_subevents:
tlv = self.event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
if tlv:
term_last = make_aware(datetime.combine(
tlv.datetime(self.event).date(),
time(hour=23, minute=59, second=59)
), self.event.timezone)
if term_last < self.now_dt:
raise CartError(error_messages['ended'])
def _extend_expiry_of_valid_existing_positions(self): def _extend_expiry_of_valid_existing_positions(self):
# Extend this user's cart session to ensure all items in the cart expire at the same time # Extend this user's cart session to ensure all items in the cart expire at the same time
@@ -152,6 +162,18 @@ class CartManager:
err = error_messages['some_subevent_ended'] err = error_messages['some_subevent_ended']
cp.addons.all().delete() cp.addons.all().delete()
cp.delete() cp.delete()
if cp.subevent:
tlv = self.event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
if tlv:
term_last = make_aware(datetime.combine(
tlv.datetime(cp.subevent).date(),
time(hour=23, minute=59, second=59)
), self.event.timezone)
if term_last < self.now_dt:
err = error_messages['some_subevent_ended']
cp.addons.all().delete()
cp.delete()
return err return err
def _update_subevents_cache(self, se_ids: List[int]): def _update_subevents_cache(self, se_ids: List[int]):
@@ -216,6 +238,16 @@ class CartManager:
if op.subevent and op.subevent.presale_has_ended: if op.subevent and op.subevent.presale_has_ended:
raise CartError(error_messages['ended']) raise CartError(error_messages['ended'])
if op.subevent:
tlv = self.event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
if tlv:
term_last = make_aware(datetime.combine(
tlv.datetime(op.subevent).date(),
time(hour=23, minute=59, second=59)
), self.event.timezone)
if term_last < self.now_dt:
raise CartError(error_messages['ended'])
if isinstance(op, self.AddOperation): if isinstance(op, self.AddOperation):
if op.item.category and op.item.category.is_addon and not (op.addon_to and op.addon_to != 'FAKE'): if op.item.category and op.item.category.is_addon and not (op.addon_to and op.addon_to != 'FAKE'):
raise CartError(error_messages['addon_only']) raise CartError(error_messages['addon_only'])

View File

@@ -71,6 +71,16 @@ class CartTest(CartTestMixin, TestCase):
assert 'alert-danger' in response.rendered_content assert 'alert-danger' in response.rendered_content
assert not CartPosition.objects.filter(cart_id=self.session_key, event=self.event).exists() assert not CartPosition.objects.filter(cart_id=self.session_key, event=self.event).exists()
def test_after_payment_period(self):
self.event.settings.payment_term_last = (now() - datetime.timedelta(days=1)).date().isoformat()
response = self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1'
}, follow=True)
self.assertRedirects(response, '/%s/%s/?require_cookie=true' % (self.orga.slug, self.event.slug),
target_status_code=200)
assert 'alert-danger' in response.rendered_content
assert not CartPosition.objects.filter(cart_id=self.session_key, event=self.event).exists()
def test_after_event(self): def test_after_event(self):
self.event.date_to = now() - timedelta(days=1) self.event.date_to = now() - timedelta(days=1)
self.event.save() self.event.save()
@@ -321,6 +331,20 @@ class CartTest(CartTestMixin, TestCase):
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event)) objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 1) self.assertEqual(len(objs), 1)
def test_subevent_payment_period_over(self):
self.event.has_subevents = True
self.event.save()
self.event.settings.payment_term_last = 'RELDATE/1/23:59:59/date_from/'
se = self.event.subevents.create(name='Foo', date_from=now(), active=True)
q = se.quotas.create(name="foo", size=None, event=self.event)
q.items.add(self.ticket)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'subevent': se.pk
}, follow=False)
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 0)
def test_subevent_sale_over(self): def test_subevent_sale_over(self):
self.event.has_subevents = True self.event.has_subevents = True
self.event.save() self.event.save()