From 4cd2381a5eda2949e30dc38b0ce246e899d27a1e Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 22 Jan 2024 17:55:32 +0100 Subject: [PATCH] Fix CartManager.apply_voucher to handle all_bundles_included --- src/pretix/base/services/cart.py | 15 ++++++++- src/tests/presale/test_cart.py | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/pretix/base/services/cart.py b/src/pretix/base/services/cart.py index 992519a180..d5c34352d7 100644 --- a/src/pretix/base/services/cart.py +++ b/src/pretix/base/services/cart.py @@ -1299,10 +1299,23 @@ class CartManager: op.position.price_after_voucher = op.price_after_voucher op.position.voucher = op.voucher - # op.posiiton.price will be set in recompute_final_prices_and_taxes + # op.position.price will be set in recompute_final_prices_and_taxes op.position.save(update_fields=['price_after_voucher', 'voucher']) vouchers_ok[op.voucher] -= 1 + if op.voucher.all_bundles_included or op.voucher.all_addons_included: + for a in op.position.addons.all(): + if a.is_bundled and op.voucher.all_bundles_included and a.price: + a.listed_price = Decimal("0.00") + a.price_after_voucher = Decimal("0.00") + # a.price will be set in recompute_final_prices_and_taxes + a.save(update_fields=['listed_price', 'price_after_voucher']) + elif not a.is_bundled and op.voucher.all_addons_included and a.price and not a.custom_price_input: + a.listed_price = Decimal("0.00") + a.price_after_voucher = Decimal("0.00") + # op.positon.price will be set in recompute_final_prices_and_taxes + a.save(update_fields=['listed_price', 'price_after_voucher']) + for p in new_cart_positions: if getattr(p, '_answers', None): if not p.pk: # We stored some to the database already before diff --git a/src/tests/presale/test_cart.py b/src/tests/presale/test_cart.py index 4d0e6b9bfe..57f54b1d7e 100644 --- a/src/tests/presale/test_cart.py +++ b/src/tests/presale/test_cart.py @@ -3643,6 +3643,62 @@ class CartBundleTest(CartTestMixin, TestCase): assert cp.price == Decimal('0.00') assert b.price == Decimal('1.50') + @classscope(attr='orga') + def test_voucher_apply_affect_bundled(self): + cp = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.ticket, + price=21.5, expires=now() + timedelta(minutes=10) + ) + a = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp, + price=2.5, expires=now() + timedelta(minutes=10), is_bundled=False + ) + b = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp, + price=1.5, expires=now() + timedelta(minutes=10), is_bundled=True + ) + v = Voucher.objects.create( + event=self.event, price_mode='set', value=Decimal('0.00'), max_usages=100, + all_bundles_included=True, all_addons_included=False, item=self.ticket, + ) + + self.cm.apply_voucher(v.code) + self.cm.commit() + cp.refresh_from_db() + b.refresh_from_db() + a.refresh_from_db() + assert cp.price == Decimal('0.00') + assert a.price == Decimal('2.50') + assert b.price == Decimal('0.00') + + @classscope(attr='orga') + def test_voucher_apply_affect_addons(self): + cp = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.ticket, + price=21.5, expires=now() + timedelta(minutes=10) + ) + a = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp, + price=1.5, expires=now() + timedelta(minutes=10), is_bundled=False + ) + b = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp, + price=1.5, expires=now() + timedelta(minutes=10), is_bundled=True + ) + v = Voucher.objects.create( + event=self.event, price_mode='set', value=Decimal('0.00'), max_usages=100, + all_addons_included=True, all_bundles_included=False, + ) + + self.cm.apply_voucher(v.code) + self.cm.commit() + cp.refresh_from_db() + b.refresh_from_db() + a.refresh_from_db() + assert cp.price == Decimal('0.00') + assert a.price == Decimal('0.00') + assert b.price == Decimal('1.50') + @classscope(attr='orga') def test_extend_base_price_changed(self): cp = CartPosition.objects.create(