diff --git a/doc/api/resources/subevents.rst b/doc/api/resources/subevents.rst index 6f2aadd53..ab658ab4a 100644 --- a/doc/api/resources/subevents.rst +++ b/doc/api/resources/subevents.rst @@ -20,6 +20,8 @@ name multi-lingual string The sub-event's event string The slug of the parent event active boolean If ``true``, the sub-event ticket shop is publicly available. +is_public boolean If ``true``, the sub-event ticket shop is publicly + shown in lists. date_from datetime The sub-event's start date date_to datetime The sub-event's end date (or ``null``) date_admission datetime The sub-event's admission date (or ``null``) @@ -48,6 +50,10 @@ meta_data dict Values set for .. versionchanged:: 2.6 The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added. +.. versionchanged:: 2.7 + + The attribute ``is_public`` has been added. + Endpoints --------- @@ -81,6 +87,7 @@ Endpoints "name": {"en": "First Sample Conference"}, "event": "sampleconf", "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, @@ -128,6 +135,7 @@ Endpoints { "name": {"en": "First Sample Conference"}, "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, @@ -157,6 +165,7 @@ Endpoints "id": 1, "name": {"en": "First Sample Conference"}, "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, @@ -207,6 +216,7 @@ Endpoints "name": {"en": "First Sample Conference"}, "event": "sampleconf", "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, @@ -270,6 +280,7 @@ Endpoints "name": {"en": "New Subevent Name"}, "event": "sampleconf", "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, @@ -353,6 +364,7 @@ Endpoints "name": {"en": "First Sample Conference"}, "event": "sampleconf", "active": false, + "is_public": true, "date_from": "2017-12-27T10:00:00Z", "date_to": null, "date_admission": null, diff --git a/src/pretix/api/serializers/event.py b/src/pretix/api/serializers/event.py index 8346ede28..988fe2e84 100644 --- a/src/pretix/api/serializers/event.py +++ b/src/pretix/api/serializers/event.py @@ -199,7 +199,7 @@ class SubEventSerializer(I18nAwareModelSerializer): class Meta: model = SubEvent fields = ('id', 'name', 'date_from', 'date_to', 'active', 'date_admission', - 'presale_start', 'presale_end', 'location', 'event', + 'presale_start', 'presale_end', 'location', 'event', 'is_public', 'item_price_overrides', 'variation_price_overrides', 'meta_data') def validate(self, data): diff --git a/src/pretix/base/migrations/0118_auto_20190423_0839.py b/src/pretix/base/migrations/0118_auto_20190423_0839.py new file mode 100644 index 000000000..ff597806d --- /dev/null +++ b/src/pretix/base/migrations/0118_auto_20190423_0839.py @@ -0,0 +1,21 @@ +# Generated by Django 2.2 on 2019-04-23 08:39 + +from django.db import migrations, models +import django.db.models.deletion +import jsonfallback.fields +import pretix.base.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0117_auto_20190418_1149'), + ] + + operations = [ + migrations.AddField( + model_name='subevent', + name='is_public', + field=models.BooleanField(default=True, help_text='If selected, this event will show up publicly on the list of dates for your event.', verbose_name='Show in lists'), + ), + ] diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 50199b168..129667c0a 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -639,22 +639,6 @@ class Event(EventMixin, LoggedModel): irs = self.get_invoice_renderers() return irs[self.settings.invoice_renderer] - @property - def active_subevents(self): - """ - Returns a queryset of active subevents. - """ - return self.subevents.filter(active=True).order_by('-date_from', 'name') - - @property - def active_future_subevents(self): - return self.subevents.filter( - Q(active=True) & ( - Q(Q(date_to__isnull=True) & Q(date_from__gte=now())) - | Q(date_to__gte=now()) - ) - ).order_by('date_from', 'name') - def subevents_annotated(self, channel): return SubEvent.annotated(self.subevents, channel) @@ -667,7 +651,7 @@ class Event(EventMixin, LoggedModel): 'name_descending': ('-name', 'date_from'), }[ordering] subevs = queryset.filter( - Q(active=True) & ( + Q(active=True) & Q(is_public=True) & ( Q(Q(date_to__isnull=True) & Q(date_from__gte=now() - timedelta(hours=24))) | Q(date_to__gte=now() - timedelta(hours=24)) ) @@ -833,6 +817,8 @@ class SubEvent(EventMixin, LoggedModel): :type event: Event :param active: Whether to show the subevent :type active: bool + :param is_public: Whether to show the subevent in lists + :type is_public: bool :param name: This event's full title :type name: str :param date_from: The datetime this event starts @@ -851,6 +837,10 @@ class SubEvent(EventMixin, LoggedModel): active = models.BooleanField(default=False, verbose_name=_("Active"), help_text=_("Only with this checkbox enabled, this date is visible in the " "frontend to users.")) + is_public = models.BooleanField(default=True, + verbose_name=_("Show in lists"), + help_text=_("If selected, this event will show up publicly on the list of dates " + "for your event.")) name = I18nCharField( max_length=200, verbose_name=_("Name"), diff --git a/src/pretix/presale/views/organizer.py b/src/pretix/presale/views/organizer.py index 8af312d45..847599c9c 100644 --- a/src/pretix/presale/views/organizer.py +++ b/src/pretix/presale/views/organizer.py @@ -128,6 +128,7 @@ class EventListMixin: tz = pytz.timezone(self.request.event.settings.timezone) next_sev = self.request.event.subevents.filter( active=True, + is_public=True, date_from__gte=now() ).select_related('event').order_by('date_from').first() @@ -152,6 +153,7 @@ class EventListMixin: event__is_public=True, event__live=True, active=True, + is_public=True, date_from__gte=now() ), self.request).select_related('event').order_by('date_from').first() @@ -261,7 +263,7 @@ def add_events_for_days(request, baseqs, before, after, ebd, timezones): def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_namespace=None): - qs = qs.filter(active=True).filter( + qs = qs.filter(active=True, is_public=True).filter( Q(Q(date_to__gte=before) & Q(date_from__lte=after)) | Q(Q(date_from__lte=after) & Q(date_to__gte=before)) | Q(Q(date_to__isnull=True) & Q(date_from__gte=before) & Q(date_from__lte=after)) @@ -382,6 +384,7 @@ class OrganizerIcalDownload(OrganizerViewMixin, View): event__organizer=self.request.organizer, event__is_public=True, event__live=True, + is_public=True, active=True ), request diff --git a/src/tests/api/test_subevents.py b/src/tests/api/test_subevents.py index e7bc22116..d8c5a1e53 100644 --- a/src/tests/api/test_subevents.py +++ b/src/tests/api/test_subevents.py @@ -74,6 +74,7 @@ TEST_SUBEVENT_RES = { 'id': 1, 'variation_price_overrides': [], 'location': None, + 'is_public': True, 'item_price_overrides': [], 'meta_data': {'type': 'Workshop'} } diff --git a/src/tests/presale/test_widget.py b/src/tests/presale/test_widget.py index 7effe6705..82452f140 100644 --- a/src/tests/presale/test_widget.py +++ b/src/tests/presale/test_widget.py @@ -334,6 +334,7 @@ class WidgetCartTest(CartTestMixin, TestCase): se1 = self.event.subevents.create(name="Present", active=True, date_from=now()) se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3)) self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3)) + self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3)) response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug)) data = json.loads(response.content.decode()) @@ -357,6 +358,7 @@ class WidgetCartTest(CartTestMixin, TestCase): se1 = self.event.subevents.create(name="Present", active=True, date_from=now()) se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3)) self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3)) + self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3)) response = self.client.get('/%s/%s/widget/product_list?style=calendar' % (self.orga.slug, self.event.slug)) settings.SITE_URL = 'http://example.com' @@ -431,6 +433,7 @@ class WidgetCartTest(CartTestMixin, TestCase): self.event.subevents.create(name="Present", active=True, date_from=now()) self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3)) self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3)) + self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3)) settings.SITE_URL = 'http://example.com' response = self.client.get('/%s/widget/product_list' % (self.orga.slug,)) @@ -467,6 +470,7 @@ class WidgetCartTest(CartTestMixin, TestCase): se1 = self.event.subevents.create(name="Present", active=True, date_from=now()) se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3)) self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3)) + self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3)) response = self.client.get('/%s/widget/product_list?style=calendar' % (self.orga.slug,)) settings.SITE_URL = 'http://example.com'