This commit is contained in:
Raphael Michel
2022-04-27 14:43:16 +02:00
committed by GitHub
parent 7730cc6170
commit 6fee0ac0a9
56 changed files with 4159 additions and 480 deletions

View File

@@ -46,15 +46,14 @@ from tests.testdummy.signals import FoobarSalesChannel
from pretix.base.decimal import round_decimal
from pretix.base.models import (
CartPosition, Event, InvoiceAddress, Item, ItemCategory, ItemVariation,
Organizer, Question, QuestionAnswer, Quota, SeatingPlan, Voucher,
CartPosition, Discount, Event, InvoiceAddress, Item, ItemCategory,
ItemVariation, Organizer, Question, QuestionAnswer, Quota, SeatingPlan,
Voucher,
)
from pretix.base.models.items import (
ItemAddOn, ItemBundle, SubEventItem, SubEventItemVariation,
)
from pretix.base.services.cart import (
CartError, CartManager, error_messages, update_tax_rates,
)
from pretix.base.services.cart import CartError, CartManager, error_messages
from pretix.testutils.scope import classscope
from pretix.testutils.sessions import get_cart_session_key
@@ -1557,7 +1556,8 @@ class CartTest(CartTestMixin, TestCase):
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, Decimal('21.00'))
self.assertEqual(objs[0].price_before_voucher, Decimal('23.00'))
self.assertEqual(objs[0].listed_price, Decimal('23.00'))
self.assertEqual(objs[0].price_after_voucher, Decimal('20.70'))
def test_voucher_free_price_before_voucher_cap(self):
with scopes_disabled():
@@ -1582,7 +1582,8 @@ class CartTest(CartTestMixin, TestCase):
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, Decimal('41.00'))
self.assertEqual(objs[0].price_before_voucher, Decimal('41.00'))
self.assertEqual(objs[0].listed_price, Decimal('23.00'))
self.assertEqual(objs[0].price_after_voucher, Decimal('20.70'))
def test_voucher_free_price_lower_bound(self):
with scopes_disabled():
@@ -1607,7 +1608,8 @@ class CartTest(CartTestMixin, TestCase):
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, Decimal('20.70'))
self.assertEqual(objs[0].price_before_voucher, Decimal('23.00'))
self.assertEqual(objs[0].listed_price, Decimal('23.00'))
self.assertEqual(objs[0].price_after_voucher, Decimal('20.70'))
def test_voucher_redemed(self):
with scopes_disabled():
@@ -1977,11 +1979,11 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=15, expires=now() + timedelta(minutes=10)
price=15, listed_price=15, price_after_voucher=15, expires=now() + timedelta(minutes=10)
)
v = Voucher.objects.create(
event=self.event, item=self.ticket, price_mode='set', value=Decimal('4.00')
@@ -2001,11 +2003,11 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=150, expires=now() + timedelta(minutes=10)
price=150, listed_price=150, price_after_voucher=150, expires=now() + timedelta(minutes=10)
)
v = Voucher.objects.create(
event=self.event, price_mode='set', value=Decimal('4.00'), max_usages=100, redeemed=99
@@ -2026,11 +2028,11 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=150, expires=now() + timedelta(minutes=10)
price=150, listed_price=150, price_after_voucher=150, expires=now() + timedelta(minutes=10)
)
v = Voucher.objects.create(
event=self.event, price_mode='set', quota=self.quota_all, value=Decimal('4.00'), max_usages=100
@@ -2051,14 +2053,14 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
v2 = Voucher.objects.create(
event=self.event, price_mode='set', quota=self.quota_all, value=Decimal('4.00'), max_usages=100
event=self.event, price_mode='set', quota=self.quota_all, value=Decimal('8.00'), max_usages=100
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=150, expires=now() + timedelta(minutes=10), voucher=v2
price=8, expires=now() + timedelta(minutes=10), voucher=v2
)
v = Voucher.objects.create(
event=self.event, price_mode='set', quota=self.quota_all, value=Decimal('4.00'), max_usages=100
@@ -2073,7 +2075,7 @@ class CartTest(CartTestMixin, TestCase):
assert cp1.voucher == v
assert cp1.price == Decimal('4.00')
assert cp2.voucher == v2
assert cp2.price == Decimal('150.00')
assert cp2.price == Decimal('8.00')
"""
def test_voucher_apply_only_positive(self):
@@ -2104,11 +2106,11 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=15, expires=now() + timedelta(minutes=10)
price=15, listed_price=15, price_after_voucher=15, expires=now() + timedelta(minutes=10)
)
v = Voucher.objects.create(
event=self.event, price_mode='set', value=Decimal('40.00'), max_usages=100,
@@ -2128,11 +2130,11 @@ class CartTest(CartTestMixin, TestCase):
with scopes_disabled():
cp1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
price=23, listed_price=23, price_after_voucher=23, expires=now() + timedelta(minutes=10)
)
cp2 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.shirt, variation=self.shirt_blue,
price=15, expires=now() + timedelta(minutes=10)
price=15, listed_price=15, price_after_voucher=15, expires=now() + timedelta(minutes=10)
)
v = Voucher.objects.create(
event=self.event, price_mode='set', value=Decimal('40.00'), max_usages=100, redeemed=100
@@ -2147,6 +2149,79 @@ class CartTest(CartTestMixin, TestCase):
assert cp1.voucher is None
assert cp2.voucher is None
def test_discount(self):
with scopes_disabled():
Discount.objects.create(event=self.event, condition_min_count=2, benefit_discount_matching_percent=20,
benefit_only_apply_to_cheapest_n_matches=1)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 1)
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, 23)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 2)
self.assertEqual({objs[0].price, objs[1].price}, {Decimal('23.00'), Decimal('18.40')})
def test_discount_and_voucher_mixed(self):
with scopes_disabled():
Discount.objects.create(event=self.event, condition_min_count=2, benefit_discount_matching_percent=50,
benefit_only_apply_to_cheapest_n_matches=1)
v = Voucher.objects.create(
event=self.event, price_mode='set', value=Decimal('4.00'), max_usages=100
)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'_voucher_code': v.code,
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 1)
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, 4)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'_voucher_code': v.code,
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 2)
self.assertEqual({objs[0].price, objs[1].price}, {Decimal('4.00'), Decimal('2.00')})
def test_discount_and_voucher_mix_forbidden(self):
with scopes_disabled():
Discount.objects.create(event=self.event, condition_min_count=2, benefit_discount_matching_percent=50,
benefit_only_apply_to_cheapest_n_matches=1, condition_ignore_voucher_discounted=True)
v = Voucher.objects.create(
event=self.event, price_mode='set', value=Decimal('4.00'), max_usages=100
)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'_voucher_code': v.code,
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 1)
self.assertEqual(objs[0].item, self.ticket)
self.assertIsNone(objs[0].variation)
self.assertEqual(objs[0].price, 4)
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'_voucher_code': v.code,
}, follow=True)
with scopes_disabled():
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
self.assertEqual(len(objs), 2)
self.assertEqual({objs[0].price, objs[1].price}, {Decimal('4.00'), Decimal('4.00')})
class CartAddonTest(CartTestMixin, TestCase):
@scopes_disabled()
@@ -2836,7 +2911,9 @@ class CartAddonTest(CartTestMixin, TestCase):
self.cm.commit()
cp1.refresh_from_db()
assert cp1.expires > now()
assert cp1.price_before_voucher == Decimal('23.00')
assert cp1.listed_price == Decimal('23.00')
assert cp1.price_after_voucher == Decimal('20.00')
assert cp1.price == Decimal('20.00')
class CartBundleTest(CartTestMixin, TestCase):
@@ -2911,7 +2988,8 @@ class CartBundleTest(CartTestMixin, TestCase):
assert cp.price == 23 - 1.5
assert cp.addons.count() == 1
assert cp.voucher == v
assert cp.price_before_voucher == 23 - 1.5
assert cp.listed_price == 23
assert cp.price_after_voucher == 23
a = cp.addons.get()
assert a.item == self.trans
assert a.price == 1.5
@@ -2934,7 +3012,8 @@ class CartBundleTest(CartTestMixin, TestCase):
assert cp.price == 23 - 1.5 - 1.5
assert cp.addons.count() == 1
assert cp.voucher == v
assert cp.price_before_voucher == 23 - 1.5
assert cp.listed_price == 23
assert cp.price_after_voucher == 23 - 1.5
a = cp.addons.get()
assert a.item == self.trans
assert a.price == 1.5
@@ -3221,13 +3300,11 @@ class CartBundleTest(CartTestMixin, TestCase):
assert cp.tax_rate == Decimal('19.00')
assert cp.tax_value == Decimal('3.43')
assert cp.addons.count() == 1
assert cp.includes_tax
a = cp.addons.first()
assert a.item == self.trans
assert a.price == 1.5
assert a.tax_rate == Decimal('7.00')
assert a.tax_value == Decimal('0.10')
assert a.includes_tax
@classscope(attr='orga')
def test_one_bundled_one_addon(self):
@@ -3421,15 +3498,14 @@ class CartBundleTest(CartTestMixin, TestCase):
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
)
update_tax_rates(self.event, self.session_key, ia)
self.cm.invoice_address = ia
self.cm.recompute_final_prices_and_taxes()
cp.refresh_from_db()
a.refresh_from_db()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
self.cm.invoice_address = ia
self.cm.commit()
@@ -3438,10 +3514,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a.refresh_from_db()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == 0
assert not a.includes_tax
@classscope(attr='orga')
def test_expired_reverse_charge_all(self):
@@ -3464,15 +3538,14 @@ class CartBundleTest(CartTestMixin, TestCase):
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
)
update_tax_rates(self.event, self.session_key, ia)
self.cm.invoice_address = ia
self.cm.recompute_final_prices_and_taxes()
cp.refresh_from_db()
a.refresh_from_db()
assert cp.price == Decimal('18.07')
assert cp.tax_rate == Decimal('0.00')
assert not cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
self.cm.invoice_address = ia
self.cm.commit()
@@ -3481,10 +3554,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a.refresh_from_db()
assert cp.price == Decimal('18.07')
assert cp.tax_rate == Decimal('0.00')
assert not cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
@classscope(attr='orga')
def test_reverse_charge_all_add(self):
@@ -3513,10 +3584,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a = CartPosition.objects.filter(addon_to__isnull=False).get()
assert cp.price == Decimal('18.07')
assert cp.tax_rate == Decimal('0.00')
assert not cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
@classscope(attr='orga')
def test_reverse_charge_bundled_add_keep_gross_price(self):
@@ -3546,10 +3615,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a = CartPosition.objects.filter(addon_to__isnull=False).get()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.50')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
@classscope(attr='orga')
def test_reverse_charge_bundled_add(self):
@@ -3578,10 +3645,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a = CartPosition.objects.filter(addon_to__isnull=False).get()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.40')
assert a.tax_rate == Decimal('0.00')
assert not a.includes_tax
@classscope(attr='orga')
def test_expired_country_taxing_only_bundled(self):
@@ -3606,17 +3671,16 @@ class CartBundleTest(CartTestMixin, TestCase):
)
a = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp,
price=1.47, expires=now() - timedelta(minutes=10), is_bundled=True, override_tax_rate=Decimal('5.00')
price=1.47, expires=now() - timedelta(minutes=10), is_bundled=True, tax_rate=Decimal('5.00')
)
update_tax_rates(self.event, self.session_key, ia)
self.cm.invoice_address = ia
self.cm.recompute_final_prices_and_taxes()
cp.refresh_from_db()
a.refresh_from_db()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
self.cm.invoice_address = ia
self.cm.commit()
@@ -3625,10 +3689,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a.refresh_from_db()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
@classscope(attr='orga')
def test_expired_country_tax_all(self):
@@ -3654,21 +3716,20 @@ class CartBundleTest(CartTestMixin, TestCase):
cp = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=21.68, expires=now() - timedelta(minutes=10), override_tax_rate=Decimal('20.00')
price=21.68, expires=now() - timedelta(minutes=10), tax_rate=Decimal('20.00')
)
a = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.trans, addon_to=cp,
price=1.47, expires=now() - timedelta(minutes=10), is_bundled=True, override_tax_rate=Decimal('5.00')
price=1.47, expires=now() - timedelta(minutes=10), is_bundled=True, tax_rate=Decimal('5.00')
)
update_tax_rates(self.event, self.session_key, ia)
self.cm.invoice_address = ia
self.cm.recompute_final_prices_and_taxes()
cp.refresh_from_db()
a.refresh_from_db()
assert cp.price == Decimal('21.68')
assert cp.tax_rate == Decimal('20.00')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
self.cm.invoice_address = ia
self.cm.commit()
@@ -3677,10 +3738,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a.refresh_from_db()
assert cp.price == Decimal('21.68')
assert cp.tax_rate == Decimal('20.0')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
@classscope(attr='orga')
def test_country_tax_all_add(self):
@@ -3718,10 +3777,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a = CartPosition.objects.filter(addon_to__isnull=False).get()
assert cp.price == Decimal('21.68')
assert cp.tax_rate == Decimal('20.00')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
@classscope(attr='orga')
def test_country_tax_bundled_add(self):
@@ -3754,10 +3811,8 @@ class CartBundleTest(CartTestMixin, TestCase):
a = CartPosition.objects.filter(addon_to__isnull=False).get()
assert cp.price == Decimal('21.50')
assert cp.tax_rate == Decimal('19.00')
assert cp.includes_tax
assert a.price == Decimal('1.47')
assert a.tax_rate == Decimal('5.00')
assert a.includes_tax
class CartSeatingTest(CartTestMixin, TestCase):