Event calendar: Respect voucher for availability (#3351)

This commit is contained in:
Raphael Michel
2023-05-24 17:52:10 +02:00
committed by GitHub
parent 63e4841460
commit c8ef681cc3
3 changed files with 82 additions and 13 deletions

View File

@@ -290,19 +290,19 @@ class EventMixin:
return safe_string(json.dumps(eventdict))
@classmethod
def annotated(cls, qs, channel='web'):
def annotated(cls, qs, channel='web', voucher=None):
from pretix.base.models import Item, ItemVariation, Quota
sq_active_item = Item.objects.using(settings.DATABASE_REPLICA).filter_available(channel=channel).filter(
sq_active_item = Item.objects.using(settings.DATABASE_REPLICA).filter_available(channel=channel, voucher=voucher).filter(
Q(variations__isnull=True)
& Q(quotas__pk=OuterRef('pk'))
).order_by().values_list('quotas__pk').annotate(
items=GroupConcat('pk', delimiter=',')
).values('items')
sq_active_variation = ItemVariation.objects.filter(
q_variation = (
Q(active=True)
& Q(sales_channels__contains=channel)
& Q(hide_without_voucher=False)
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
& Q(item__active=True)
@@ -310,10 +310,23 @@ class EventMixin:
& Q(Q(item__available_until__isnull=True) | Q(item__available_until__gte=now()))
& Q(Q(item__category__isnull=True) | Q(item__category__is_addon=False))
& Q(item__sales_channels__contains=channel)
& Q(item__hide_without_voucher=False)
& Q(item__require_bundling=False)
& Q(quotas__pk=OuterRef('pk'))
).order_by().values_list('quotas__pk').annotate(
)
if voucher:
if voucher.variation_id:
q_variation &= Q(pk=voucher.variation_id)
elif voucher.item_id:
q_variation &= Q(item_id=voucher.item_id)
elif voucher.quota_id:
q_variation &= Q(quotas__in=[voucher.quota_id])
if not voucher or not voucher.show_hidden_items:
q_variation &= Q(hide_without_voucher=False)
q_variation &= Q(item__hide_without_voucher=False)
sq_active_variation = ItemVariation.objects.filter(q_variation).order_by().values_list('quotas__pk').annotate(
items=GroupConcat('pk', delimiter=',')
).values('items')
quota_base_qs = Quota.objects.using(settings.DATABASE_REPLICA).filter(
@@ -1133,8 +1146,8 @@ class Event(EventMixin, LoggedModel):
irs = self.get_invoice_renderers()
return irs[self.settings.invoice_renderer]
def subevents_annotated(self, channel):
return SubEvent.annotated(self.subevents, channel)
def subevents_annotated(self, channel, voucher=None):
return SubEvent.annotated(self.subevents, channel, voucher)
def subevents_sorted(self, queryset):
ordering = self.settings.get('frontpage_subevent_ordering', default='date_ascending', as_type=str)
@@ -1454,10 +1467,10 @@ class SubEvent(EventMixin, LoggedModel):
return qs_annotated
@classmethod
def annotated(cls, qs, channel='web'):
def annotated(cls, qs, channel='web', voucher=None):
from .items import SubEventItem, SubEventItemVariation
qs = super().annotated(qs, channel)
qs = super().annotated(qs, channel, voucher=voucher)
qs = qs.annotate(
disabled_items=Coalesce(
Subquery(

View File

@@ -597,7 +597,13 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
ebd = defaultdict(list)
add_subevents_for_days(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request),
filter_qs_by_attr(
self.request.event.subevents_annotated(
self.request.sales_channel.identifier,
voucher,
).using(settings.DATABASE_REPLICA),
self.request
),
limit_before, after, ebd, set(), self.request.event,
self.kwargs.get('cart_namespace'),
voucher,
@@ -649,7 +655,13 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
ebd = defaultdict(list)
add_subevents_for_days(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request),
filter_qs_by_attr(
self.request.event.subevents_annotated(
self.request.sales_channel.identifier,
voucher=voucher,
).using(settings.DATABASE_REPLICA),
self.request
),
limit_before, after, ebd, set(), self.request.event,
self.kwargs.get('cart_namespace'),
voucher,
@@ -692,7 +704,13 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
)
else:
context['subevent_list'] = self.request.event.subevents_sorted(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request)
filter_qs_by_attr(
self.request.event.subevents_annotated(
self.request.sales_channel.identifier,
voucher=voucher,
).using(settings.DATABASE_REPLICA),
self.request
)
)
if self.request.event.settings.event_list_available_only and not voucher:
context['subevent_list'] = [

View File

@@ -2206,6 +2206,44 @@ class EventTest(TestCase):
q.items.add(item)
assert Event.annotated(Event.objects).first().active_quotas == []
@classscope(attr='organizer')
def test_active_quotas_annotation_product_hidden_by_voucher(self):
event = Event.objects.create(
organizer=self.organizer, name='Download', slug='download',
date_from=now()
)
q = Quota.objects.create(event=event, name='Quota', size=2)
item = Item.objects.create(event=event, name='Early-bird ticket', default_price=0, hide_without_voucher=True)
q.items.add(item)
voucher = Voucher.objects.create(event=event, code='a', item=item, show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == [q]
voucher = Voucher.objects.create(event=event, code='b', item=item, show_hidden_items=False)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == []
voucher = Voucher.objects.create(event=event, code='c', show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == [q]
voucher = Voucher.objects.create(event=event, code='d', quota=q, show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == [q]
item2 = Item.objects.create(event=event, name='Early-bird ticket', default_price=0)
var = item2.variations.create(item=item2, value='Test', hide_without_voucher=True)
var2 = item2.variations.create(item=item2, value='Other test', hide_without_voucher=True, active=False)
q.items.remove(item)
q.items.add(item2)
q.variations.add(var)
voucher = Voucher.objects.create(event=event, code='e', item=item2, variation=var, show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == [q]
voucher = Voucher.objects.create(event=event, code='f', item=item2, variation=var2, show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == []
voucher = Voucher.objects.create(event=event, code='g', quota=q, show_hidden_items=True)
assert Event.annotated(Event.objects, voucher=voucher).first().active_quotas == [q]
@classscope(attr='organizer')
def test_active_quotas_annotation_product_addon(self):
event = Event.objects.create(