mirror of
https://github.com/pretix/pretix.git
synced 2026-05-17 17:14:04 +00:00
CartManager: allow extending expiry of valid positions only up to max_extend
This commit is contained in:
@@ -46,6 +46,7 @@ from django.conf import settings
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import DatabaseError, transaction
|
from django.db import DatabaseError, transaction
|
||||||
from django.db.models import Count, Exists, IntegerField, OuterRef, Q, Value
|
from django.db.models import Count, Exists, IntegerField, OuterRef, Q, Value
|
||||||
|
from django.db.models.aggregates import Max
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.timezone import make_aware, now
|
from django.utils.timezone import make_aware, now
|
||||||
from django.utils.translation import (
|
from django.utils.translation import (
|
||||||
@@ -304,6 +305,7 @@ class CartManager:
|
|||||||
else:
|
else:
|
||||||
self._reservation_time = timedelta(minutes=self.event.settings.get('reservation_time', as_type=int))
|
self._reservation_time = timedelta(minutes=self.event.settings.get('reservation_time', as_type=int))
|
||||||
self._expiry = self.real_now_dt + self._reservation_time
|
self._expiry = self.real_now_dt + self._reservation_time
|
||||||
|
self._max_expiry_extend = self.real_now_dt + (self._reservation_time * 11)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def positions(self):
|
def positions(self):
|
||||||
@@ -318,14 +320,6 @@ class CartManager:
|
|||||||
self._seated_cache[item, subevent] = item.seat_category_mappings.filter(subevent=subevent).exists()
|
self._seated_cache[item, subevent] = item.seat_category_mappings.filter(subevent=subevent).exists()
|
||||||
return self._seated_cache[item, subevent]
|
return self._seated_cache[item, subevent]
|
||||||
|
|
||||||
def _calculate_expiry(self):
|
|
||||||
if self._explicit_expiry:
|
|
||||||
self._expiry = self._explicit_expiry
|
|
||||||
else:
|
|
||||||
self._expiry = self.real_now_dt + timedelta(
|
|
||||||
minutes=self.event.settings.get('reservation_time', as_type=int)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_presale_dates(self):
|
def _check_presale_dates(self):
|
||||||
if self.event.presale_start and time_machine_now(self.real_now_dt) < self.event.presale_start:
|
if self.event.presale_start and time_machine_now(self.real_now_dt) < self.event.presale_start:
|
||||||
raise CartError(error_messages['not_started'])
|
raise CartError(error_messages['not_started'])
|
||||||
@@ -342,9 +336,18 @@ class CartManager:
|
|||||||
raise CartError(error_messages['payment_ended'])
|
raise CartError(error_messages['payment_ended'])
|
||||||
|
|
||||||
def _extend_expiry_of_valid_existing_positions(self):
|
def _extend_expiry_of_valid_existing_positions(self):
|
||||||
|
# Make sure we do not extend past the max_extend timestamp, allowing users to extend their valid positions up
|
||||||
|
# to 11 times the reservation time. After that, positions will expire, but can still be re-validated using
|
||||||
|
# ExtendOperation.
|
||||||
|
max_extend_existing = self.positions.filter(expires__gt=self.real_now_dt).aggregate(m=Max('max_extend'))['m']
|
||||||
|
if max_extend_existing:
|
||||||
|
self._expiry = min(self._expiry, max_extend_existing)
|
||||||
|
self._max_expiry_extend = max_extend_existing
|
||||||
|
|
||||||
# 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
|
||||||
# We can extend the reservation of items which are not yet expired without risk
|
# We can extend the reservation of items which are not yet expired without risk
|
||||||
self.positions.filter(expires__gt=self.real_now_dt).update(expires=self._expiry)
|
if self._expiry > self.real_now_dt:
|
||||||
|
self.positions.filter(expires__gt=self.real_now_dt).update(expires=self._expiry)
|
||||||
|
|
||||||
def _delete_out_of_timeframe(self):
|
def _delete_out_of_timeframe(self):
|
||||||
err = None
|
err = None
|
||||||
@@ -1259,6 +1262,7 @@ class CartManager:
|
|||||||
item=op.item,
|
item=op.item,
|
||||||
variation=op.variation,
|
variation=op.variation,
|
||||||
expires=self._expiry,
|
expires=self._expiry,
|
||||||
|
max_extend=self._max_expiry_extend,
|
||||||
cart_id=self.cart_id,
|
cart_id=self.cart_id,
|
||||||
voucher=op.voucher,
|
voucher=op.voucher,
|
||||||
addon_to=op.addon_to if op.addon_to else None,
|
addon_to=op.addon_to if op.addon_to else None,
|
||||||
@@ -1307,7 +1311,9 @@ class CartManager:
|
|||||||
event=self.event,
|
event=self.event,
|
||||||
item=b.item,
|
item=b.item,
|
||||||
variation=b.variation,
|
variation=b.variation,
|
||||||
expires=self._expiry, cart_id=self.cart_id,
|
expires=self._expiry,
|
||||||
|
max_extend=self._max_expiry_extend,
|
||||||
|
cart_id=self.cart_id,
|
||||||
voucher=None,
|
voucher=None,
|
||||||
addon_to=cp,
|
addon_to=cp,
|
||||||
subevent=b.subevent,
|
subevent=b.subevent,
|
||||||
@@ -1334,12 +1340,13 @@ class CartManager:
|
|||||||
op.position.delete()
|
op.position.delete()
|
||||||
elif available_count == 1:
|
elif available_count == 1:
|
||||||
op.position.expires = self._expiry
|
op.position.expires = self._expiry
|
||||||
|
op.position.max_extend = self._max_expiry_extend
|
||||||
op.position.listed_price = op.listed_price
|
op.position.listed_price = op.listed_price
|
||||||
op.position.price_after_voucher = op.price_after_voucher
|
op.position.price_after_voucher = op.price_after_voucher
|
||||||
# op.position.price will be updated by recompute_final_prices_and_taxes()
|
# op.position.price will be updated by recompute_final_prices_and_taxes()
|
||||||
if op.position.pk not in deleted_positions:
|
if op.position.pk not in deleted_positions:
|
||||||
try:
|
try:
|
||||||
op.position.save(force_update=True, update_fields=['expires', 'listed_price', 'price_after_voucher'])
|
op.position.save(force_update=True, update_fields=['expires', 'max_extend', 'listed_price', 'price_after_voucher'])
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
# Best effort... The position might have been deleted in the meantime!
|
# Best effort... The position might have been deleted in the meantime!
|
||||||
pass
|
pass
|
||||||
@@ -1434,8 +1441,6 @@ class CartManager:
|
|||||||
err = self.extend_expired_positions() or err
|
err = self.extend_expired_positions() or err
|
||||||
err = err or self._check_min_per_voucher()
|
err = err or self._check_min_per_voucher()
|
||||||
|
|
||||||
self.real_now_dt = now()
|
|
||||||
|
|
||||||
self._extend_expiry_of_valid_existing_positions()
|
self._extend_expiry_of_valid_existing_positions()
|
||||||
err = self._perform_operations() or err
|
err = self._perform_operations() or err
|
||||||
self.recompute_final_prices_and_taxes()
|
self.recompute_final_prices_and_taxes()
|
||||||
|
|||||||
Reference in New Issue
Block a user