forked from CGM_Public/pretix_original
Compare commits
1 Commits
reldatetim
...
subevent-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df656d1580 |
@@ -313,38 +313,9 @@ class EventMixin:
|
|||||||
items=GroupConcat('pk', delimiter=',')
|
items=GroupConcat('pk', delimiter=',')
|
||||||
).values('items')
|
).values('items')
|
||||||
|
|
||||||
q_variation = (
|
sq_active_variation = ItemVariation.objects.filter_available(channel=channel, voucher=voucher).filter(
|
||||||
Q(active=True)
|
Q(quotas__pk=OuterRef('pk'))
|
||||||
& Q(Q(available_from__isnull=True) | Q(available_from__lte=time_machine_now()))
|
).order_by().values_list('quotas__pk').annotate(
|
||||||
& Q(Q(available_until__isnull=True) | Q(available_until__gte=time_machine_now()))
|
|
||||||
& Q(item__active=True)
|
|
||||||
& Q(Q(item__available_from__isnull=True) | Q(item__available_from__lte=time_machine_now()))
|
|
||||||
& Q(Q(item__available_until__isnull=True) | Q(item__available_until__gte=time_machine_now()))
|
|
||||||
& Q(Q(item__category__isnull=True) | Q(item__category__is_addon=False))
|
|
||||||
& Q(item__require_bundling=False)
|
|
||||||
& Q(quotas__pk=OuterRef('pk'))
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(channel, str):
|
|
||||||
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
|
|
||||||
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__identifier=channel))
|
|
||||||
else:
|
|
||||||
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels=channel))
|
|
||||||
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels=channel))
|
|
||||||
|
|
||||||
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=',')
|
items=GroupConcat('pk', delimiter=',')
|
||||||
).values('items')
|
).values('items')
|
||||||
quota_base_qs = Quota.objects.using(settings.DATABASE_REPLICA).filter(
|
quota_base_qs = Quota.objects.using(settings.DATABASE_REPLICA).filter(
|
||||||
|
|||||||
@@ -303,6 +303,48 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False):
|
|||||||
return qs.filter(q)
|
return qs.filter(q)
|
||||||
|
|
||||||
|
|
||||||
|
def filter_variations_available(qs, channel='web', voucher=None, allow_addons=False):
|
||||||
|
# Channel can currently be a SalesChannel or a str, since we need that compatibility, but a SalesChannel
|
||||||
|
# makes the query SIGNIFICANTLY faster
|
||||||
|
from .organizer import SalesChannel
|
||||||
|
|
||||||
|
assert isinstance(channel, (SalesChannel, str))
|
||||||
|
q = (
|
||||||
|
Q(active=True)
|
||||||
|
& Q(Q(available_from__isnull=True) | Q(available_from__lte=time_machine_now()))
|
||||||
|
& Q(Q(available_until__isnull=True) | Q(available_until__gte=time_machine_now()))
|
||||||
|
& Q(item__active=True)
|
||||||
|
& Q(Q(item__available_from__isnull=True) | Q(item__available_from__lte=time_machine_now()))
|
||||||
|
& Q(Q(item__available_until__isnull=True) | Q(item__available_until__gte=time_machine_now()))
|
||||||
|
& Q(Q(item__category__isnull=True) | Q(item__category__is_addon=False))
|
||||||
|
& Q(item__require_bundling=False)
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(channel, str):
|
||||||
|
q &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
|
||||||
|
q &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__identifier=channel))
|
||||||
|
else:
|
||||||
|
q &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels=channel))
|
||||||
|
q &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels=channel))
|
||||||
|
|
||||||
|
if not allow_addons:
|
||||||
|
q &= Q(Q(item__category__isnull=True) | Q(item__category__is_addon=False))
|
||||||
|
|
||||||
|
if voucher:
|
||||||
|
if voucher.variation_id:
|
||||||
|
q &= Q(pk=voucher.variation_id)
|
||||||
|
elif voucher.item_id:
|
||||||
|
q &= Q(item_id=voucher.item_id)
|
||||||
|
elif voucher.quota_id:
|
||||||
|
q &= Q(quotas__in=[voucher.quota_id])
|
||||||
|
|
||||||
|
if not voucher or not voucher.show_hidden_items:
|
||||||
|
q &= Q(hide_without_voucher=False)
|
||||||
|
q &= Q(item__hide_without_voucher=False)
|
||||||
|
|
||||||
|
return qs.filter(q)
|
||||||
|
|
||||||
|
|
||||||
class ItemQuerySet(models.QuerySet):
|
class ItemQuerySet(models.QuerySet):
|
||||||
def filter_available(self, channel='web', voucher=None, allow_addons=False):
|
def filter_available(self, channel='web', voucher=None, allow_addons=False):
|
||||||
return filter_available(self, channel, voucher, allow_addons)
|
return filter_available(self, channel, voucher, allow_addons)
|
||||||
@@ -317,6 +359,20 @@ class ItemQuerySetManager(ScopedManager(organizer='event__organizer').__class__)
|
|||||||
return filter_available(self.get_queryset(), channel, voucher, allow_addons)
|
return filter_available(self.get_queryset(), channel, voucher, allow_addons)
|
||||||
|
|
||||||
|
|
||||||
|
class ItemVariationQuerySet(models.QuerySet):
|
||||||
|
def filter_available(self, channel='web', voucher=None, allow_addons=False):
|
||||||
|
return filter_variations_available(self, channel, voucher, allow_addons)
|
||||||
|
|
||||||
|
|
||||||
|
class ItemVariationQuerySetManager(ScopedManager(organizer='item__event__organizer').__class__):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self._queryset_class = ItemVariationQuerySet
|
||||||
|
|
||||||
|
def filter_available(self, channel='web', voucher=None, allow_addons=False):
|
||||||
|
return filter_variations_available(self.get_queryset(), channel, voucher, allow_addons)
|
||||||
|
|
||||||
|
|
||||||
class Item(LoggedModel):
|
class Item(LoggedModel):
|
||||||
"""
|
"""
|
||||||
An item is a thing which can be sold. It belongs to an event and may or may not belong to a category.
|
An item is a thing which can be sold. It belongs to an event and may or may not belong to a category.
|
||||||
@@ -1199,7 +1255,7 @@ class ItemVariation(models.Model):
|
|||||||
help_text=_('This text will be shown by the check-in app if a ticket of this type is scanned.')
|
help_text=_('This text will be shown by the check-in app if a ticket of this type is scanned.')
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = ScopedManager(organizer='item__event__organizer')
|
objects = ItemVariationQuerySetManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Product variation")
|
verbose_name = _("Product variation")
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ from django.views.generic.base import TemplateResponseMixin
|
|||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
|
|
||||||
from pretix.base.models import Customer, Membership, Order
|
from pretix.base.models import Customer, Membership, Order
|
||||||
from pretix.base.models.items import Question
|
from pretix.base.models.items import ItemAddOn, ItemVariation, Question
|
||||||
from pretix.base.models.orders import (
|
from pretix.base.models.orders import (
|
||||||
InvoiceAddress, OrderPayment, QuestionAnswer,
|
InvoiceAddress, OrderPayment, QuestionAnswer,
|
||||||
)
|
)
|
||||||
@@ -486,9 +486,33 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
label = pgettext_lazy('checkoutflow', 'Add-on products')
|
label = pgettext_lazy('checkoutflow', 'Add-on products')
|
||||||
icon = 'puzzle-piece'
|
icon = 'puzzle-piece'
|
||||||
|
|
||||||
|
def _is_applicable(self, request):
|
||||||
|
categories = set(ItemAddOn.objects.filter(
|
||||||
|
base_item_id__in=get_cart(request).values_list("item_id", flat=True)
|
||||||
|
).values_list("addon_category_id", flat=True))
|
||||||
|
if not categories:
|
||||||
|
return False
|
||||||
|
|
||||||
|
has_available_addons = (
|
||||||
|
self.event.items.filter_available(
|
||||||
|
channel=request.sales_channel,
|
||||||
|
allow_addons=True
|
||||||
|
).filter(
|
||||||
|
variations__isnull=True,
|
||||||
|
category__in=categories,
|
||||||
|
).exists() or ItemVariation.objects.filter_available(
|
||||||
|
channel=request.sales_channel,
|
||||||
|
allow_addons=True
|
||||||
|
).filter(
|
||||||
|
item__event=self.event,
|
||||||
|
item__category__in=categories,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return has_available_addons
|
||||||
|
|
||||||
def is_applicable(self, request):
|
def is_applicable(self, request):
|
||||||
if not hasattr(request, '_checkoutflow_addons_applicable'):
|
if not hasattr(request, '_checkoutflow_addons_applicable'):
|
||||||
request._checkoutflow_addons_applicable = get_cart(request).filter(item__addons__isnull=False).exists()
|
request._checkoutflow_addons_applicable = self._is_applicable(request)
|
||||||
return request._checkoutflow_addons_applicable
|
return request._checkoutflow_addons_applicable
|
||||||
|
|
||||||
def is_completed(self, request, warn=False):
|
def is_completed(self, request, warn=False):
|
||||||
|
|||||||
Reference in New Issue
Block a user