mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
Fix #522 -- Do not allow any orders after the last date of payments
This commit is contained in:
@@ -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'])
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user