mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
Add sub-events and relative date settings (#503)
* Data model * little crud * SubEventItemForm etc * Drop SubEventItem.active, quota editor * Fix failing tests * First frontend stuff * Addons form stuff * Quota calculation * net price display on EventIndex * Add tests, solve some bugs * Correct quota selection in more places, consolidate pricing logic * Fix failing quota tests * Fix TypeError * Add tests for checkout * Fixed a bug in QuotaForm * Prevent immutable cart if a quota was removed from an item * Add tests for pricing * Handle waiting list * Filter in check-in list * Fixed import lost in rebase * Fix waiting list widget * Voucher management * Voucher redemption * Fix broken tests * Add subevents to OrderChangeManager * Create a subevent during event creation * Fix bulk voucher creation * Introduce subevent.active * Copy from for subevents * Show active in list * ICal download for subevents * Check start and end of presale * Failing tests / show cart logic * Test * Rebase migrations * REST API integration of sub-events * Integrate quota calculation into the traditional quota form * Make subevent argument to add_position optional * Log-display foo * pretixdroid and subevents * Filter by subevent * Add more tests * Some mor tests * Rebase fixes * More tests * Relative dates * Restrict selection in relative datetime widgets * Filter subevent list * Re-label has_subevents * Rebase fixes, subevents in calendar view * Performance and caching issues * Refactor calendar templates * Permission tests * Calendar fixes and month selection * subevent selection * Rename subevents to dates * Add tests for calendar views
This commit is contained in:
@@ -13,7 +13,7 @@ from pretix.base.models import (
|
||||
CartPosition, Event, Item, ItemCategory, Order, OrderPosition, Organizer,
|
||||
Question, Quota, Voucher,
|
||||
)
|
||||
from pretix.base.models.items import ItemAddOn, ItemVariation
|
||||
from pretix.base.models.items import ItemAddOn, ItemVariation, SubEventItem
|
||||
|
||||
|
||||
class CheckoutTestCase(TestCase):
|
||||
@@ -300,6 +300,26 @@ class CheckoutTestCase(TestCase):
|
||||
session[key] = value
|
||||
session.save()
|
||||
|
||||
def test_subevent(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
q = se.quotas.create(name="foo", size=None, event=self.event)
|
||||
q.items.add(self.ticket)
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10), subevent=se
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertEqual(len(doc.select(".thank-you")), 1)
|
||||
self.assertFalse(CartPosition.objects.filter(id=cr1.id).exists())
|
||||
self.assertEqual(Order.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.first().subevent, se)
|
||||
|
||||
def test_free_price(self):
|
||||
self.ticket.free_price = True
|
||||
self.ticket.save()
|
||||
@@ -331,6 +351,29 @@ class CheckoutTestCase(TestCase):
|
||||
self.assertEqual(Order.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.count(), 1)
|
||||
|
||||
def test_subevent_confirm_expired_available(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
se2 = self.event.subevents.create(name='Foo', date_from=now())
|
||||
self.quota_tickets.size = 0
|
||||
self.quota_tickets.subevent = se2
|
||||
self.quota_tickets.save()
|
||||
q2 = se.quotas.create(event=self.event, size=1, name='Bar')
|
||||
q2.items.add(self.ticket)
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertEqual(len(doc.select(".thank-you")), 1)
|
||||
self.assertFalse(CartPosition.objects.filter(id=cr1.id).exists())
|
||||
self.assertEqual(Order.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.count(), 1)
|
||||
|
||||
def test_confirm_expired_available(self):
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
@@ -345,6 +388,25 @@ class CheckoutTestCase(TestCase):
|
||||
self.assertEqual(Order.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.count(), 1)
|
||||
|
||||
def test_subevent_confirm_price_changed(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
q = se.quotas.create(name="foo", size=None, event=self.event)
|
||||
q.items.add(self.ticket)
|
||||
SubEventItem.objects.create(subevent=se, item=self.ticket, price=24)
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertEqual(len(doc.select(".alert-danger")), 1)
|
||||
cr1 = CartPosition.objects.get(id=cr1.id)
|
||||
self.assertEqual(cr1.price, 24)
|
||||
|
||||
def test_confirm_price_changed(self):
|
||||
self.ticket.default_price = 24
|
||||
self.ticket.save()
|
||||
@@ -663,6 +725,35 @@ class CheckoutTestCase(TestCase):
|
||||
self.assertEqual(Order.objects.count(), 1)
|
||||
self.assertEqual(OrderPosition.objects.count(), 1)
|
||||
|
||||
def test_subevent_confirm_expired_partial(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
se2 = self.event.subevents.create(name='Foo', date_from=now())
|
||||
self.quota_tickets.size = 10
|
||||
self.quota_tickets.subevent = se2
|
||||
self.quota_tickets.save()
|
||||
q2 = se.quotas.create(event=self.event, size=1, name='Bar')
|
||||
q2.items.add(self.ticket)
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se2
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertEqual(len(doc.select(".alert-danger")), 1)
|
||||
self.assertEqual(CartPosition.objects.filter(cart_id=self.session_key).count(), 2)
|
||||
|
||||
def test_confirm_expired_partial(self):
|
||||
self.quota_tickets.size = 1
|
||||
self.quota_tickets.save()
|
||||
@@ -862,3 +953,83 @@ class CheckoutTestCase(TestCase):
|
||||
response = self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug))
|
||||
self.assertRedirects(response, '/%s/%s/checkout/addons/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
|
||||
def test_set_addons_subevent(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
self.workshopquota.size = 1
|
||||
self.workshopquota.subevent = se
|
||||
self.workshopquota.save()
|
||||
SubEventItem.objects.create(subevent=se, item=self.workshop1, price=42)
|
||||
|
||||
ItemAddOn.objects.create(base_item=self.ticket, addon_category=self.workshopcat, min_count=1)
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
|
||||
response = self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/addons/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
assert 'Workshop 1 (+ EUR 42.00)' in response.rendered_content
|
||||
|
||||
def test_set_addons_subevent_net_prices(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.settings.display_net_prices = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now())
|
||||
self.workshopquota.size = 1
|
||||
self.workshopquota.subevent = se
|
||||
self.workshopquota.save()
|
||||
self.workshop1.tax_rate = 19
|
||||
self.workshop1.save()
|
||||
self.workshop2.tax_rate = 19
|
||||
self.workshop2.save()
|
||||
SubEventItem.objects.create(subevent=se, item=self.workshop1, price=42)
|
||||
|
||||
ItemAddOn.objects.create(base_item=self.ticket, addon_category=self.workshopcat, min_count=1)
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10), subevent=se
|
||||
)
|
||||
|
||||
response = self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/addons/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
assert 'Workshop 1 (+ EUR 35.29 plus 19.00% taxes)' in response.rendered_content
|
||||
assert 'A (+ EUR 10.08 plus 19.00% taxes)' in response.rendered_content
|
||||
|
||||
def test_confirm_subevent_presale_not_yet(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.settings.display_net_prices = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now(), presale_start=now() + datetime.timedelta(days=1))
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10), subevent=se
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertGreaterEqual(len(doc.select(".alert-danger")), 1)
|
||||
assert 'presale period for one of the events in your cart has not yet started.' in response.rendered_content
|
||||
assert not CartPosition.objects.filter(cart_id=self.session_key).exists()
|
||||
|
||||
def test_confirm_subevent_presale_over(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.settings.display_net_prices = True
|
||||
self.event.save()
|
||||
se = self.event.subevents.create(name='Foo', date_from=now(), presale_end=now() - datetime.timedelta(days=1))
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10), subevent=se
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertGreaterEqual(len(doc.select(".alert-danger")), 1)
|
||||
assert 'presale period for one of the events in your cart has ended.' in response.rendered_content
|
||||
assert not CartPosition.objects.filter(cart_id=self.session_key).exists()
|
||||
|
||||
Reference in New Issue
Block a user