Fix off-by-one error in voucher validation during cart extension (#5716)

* Fix typo in calculation

* Do not double-call extend_expired_positions in tests, make it private
This commit is contained in:
Raphael Michel
2025-12-18 14:47:56 +01:00
committed by GitHub
parent 5d67a4fa33
commit 409e64d5f2
2 changed files with 4 additions and 8 deletions

View File

@@ -632,7 +632,7 @@ class CartManager:
else: else:
raise e raise e
def extend_expired_positions(self): def _extend_expired_positions(self):
requires_seat = Exists( requires_seat = Exists(
SeatCategoryMapping.objects.filter( SeatCategoryMapping.objects.filter(
Q(product=OuterRef('item')) Q(product=OuterRef('item'))
@@ -702,7 +702,7 @@ class CartManager:
err = error_messages['positions_removed'] % str(e) err = error_messages['positions_removed'] % str(e)
if cp.voucher: if cp.voucher:
self._voucher_use_diff[cp.voucher] += 2 self._voucher_use_diff[cp.voucher] += 1
self._operations.append(op) self._operations.append(op)
return err return err
@@ -1556,7 +1556,7 @@ class CartManager:
self._check_max_cart_size() self._check_max_cart_size()
err = self._delete_out_of_timeframe() err = self._delete_out_of_timeframe()
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._extend_expiry_of_valid_existing_positions() self._extend_expiry_of_valid_existing_positions()

View File

@@ -2730,7 +2730,6 @@ class CartAddonTest(CartTestMixin, TestCase):
item=self.workshop1, price=Decimal('0.00'), item=self.workshop1, price=Decimal('0.00'),
event=self.event, cart_id=self.session_key, addon_to=cp1 event=self.event, cart_id=self.session_key, addon_to=cp1
) )
self.cm.extend_expired_positions()
self.cm.commit() self.cm.commit()
cp2.refresh_from_db() cp2.refresh_from_db()
assert cp2.expires > now() assert cp2.expires > now()
@@ -2753,7 +2752,6 @@ class CartAddonTest(CartTestMixin, TestCase):
item=self.workshop1, price=Decimal('0.00'), item=self.workshop1, price=Decimal('0.00'),
event=self.event, cart_id=self.session_key, addon_to=cp1 event=self.event, cart_id=self.session_key, addon_to=cp1
) )
self.cm.extend_expired_positions()
with self.assertRaises(CartError): with self.assertRaises(CartError):
self.cm.commit() self.cm.commit()
assert CartPosition.objects.count() == 0 assert CartPosition.objects.count() == 0
@@ -3421,7 +3419,6 @@ class CartAddonTest(CartTestMixin, TestCase):
item=self.workshop1, price=Decimal('12.00'), item=self.workshop1, price=Decimal('12.00'),
event=self.event, cart_id=self.session_key, addon_to=cp1 event=self.event, cart_id=self.session_key, addon_to=cp1
) )
self.cm.extend_expired_positions()
self.cm.commit() self.cm.commit()
cp1.refresh_from_db() cp1.refresh_from_db()
cp2.refresh_from_db() cp2.refresh_from_db()
@@ -3448,13 +3445,12 @@ class CartAddonTest(CartTestMixin, TestCase):
@classscope(attr='orga') @classscope(attr='orga')
def test_expand_expired_refresh_voucher(self): def test_expand_expired_refresh_voucher(self):
v = Voucher.objects.create(item=self.ticket, value=Decimal('20.00'), event=self.event, price_mode='set', v = Voucher.objects.create(item=self.ticket, value=Decimal('20.00'), event=self.event, price_mode='set',
valid_until=now() + timedelta(days=2), max_usages=999, redeemed=0) valid_until=now() + timedelta(days=2), max_usages=1, redeemed=0)
cp1 = CartPosition.objects.create( cp1 = CartPosition.objects.create(
expires=now() - timedelta(minutes=10), max_extend=now() + 10 * self.cart_reservation_time, expires=now() - timedelta(minutes=10), max_extend=now() + 10 * self.cart_reservation_time,
item=self.ticket, price=Decimal('21.50'), item=self.ticket, price=Decimal('21.50'),
event=self.event, cart_id=self.session_key, voucher=v event=self.event, cart_id=self.session_key, voucher=v
) )
self.cm.extend_expired_positions()
self.cm.commit() self.cm.commit()
cp1.refresh_from_db() cp1.refresh_from_db()
assert cp1.expires > now() assert cp1.expires > now()