implement cross_selling_visibility "always" and "products"

This commit is contained in:
Mira Weller
2024-05-28 18:50:08 +02:00
parent 2cd5d87da4
commit a0d865cf4f
8 changed files with 197 additions and 116 deletions

View File

@@ -142,6 +142,18 @@ class ItemCategory(LoggedModel):
verbose_name_plural = _("Product categories")
ordering = ('position', 'id')
def cross_sell_visible(self, cart_positions):
if self.cross_selling_mode is None:
return False
if self.cross_selling_condition == 'always':
return True
if self.cross_selling_condition == 'products':
match = set(match.pk for match in self.cross_selling_match_products.only('pk')) # TODO prefetch this
return any(pos.item.pk in match for pos in cart_positions)
if self.cross_selling_condition == 'discounts':
# TODO not sure how to do this yet
return False
def __str__(self):
name = self.internal_name or self.name
if self.is_addon:
@@ -295,7 +307,7 @@ class SubEventItemVariation(models.Model):
return True
def filter_available(qs, channel='web', voucher=None, allow_addons=False):
def filter_available(qs, channel='web', voucher=None, allow_addons=False, allow_cross_sell=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
@@ -316,6 +328,8 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False):
if not allow_addons:
q &= Q(Q(category__isnull=True) | Q(category__is_addon=False))
if not allow_cross_sell:
q &= Q(Q(category__isnull=True) | ~Q(category__cross_selling_mode='only'))
if voucher:
if voucher.item_id:
@@ -329,8 +343,8 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False):
class ItemQuerySet(models.QuerySet):
def filter_available(self, channel='web', voucher=None, allow_addons=False):
return filter_available(self, channel, voucher, allow_addons)
def filter_available(self, channel='web', voucher=None, allow_addons=False, allow_cross_sell=False):
return filter_available(self, channel, voucher, allow_addons, allow_cross_sell)
class ItemQuerySetManager(ScopedManager(organizer='event__organizer').__class__):
@@ -338,8 +352,8 @@ class ItemQuerySetManager(ScopedManager(organizer='event__organizer').__class__)
super().__init__()
self._queryset_class = ItemQuerySet
def filter_available(self, channel='web', voucher=None, allow_addons=False):
return filter_available(self.get_queryset(), channel, voucher, allow_addons)
def filter_available(self, channel='web', voucher=None, allow_addons=False, allow_cross_sell=False):
return filter_available(self.get_queryset(), channel, voucher, allow_addons, allow_cross_sell)
class Item(LoggedModel):

View File

@@ -1610,7 +1610,7 @@ def clear_cart(self, event: Event, cart_id: str=None, locale='en', sales_channel
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def set_cart_addons(self, event: Event, addons: List[dict], cart_id: str=None, locale='en',
def set_cart_addons(self, event: Event, addons: List[dict], add_to_cart_items: List[dict], cart_id: str=None, locale='en',
invoice_address: int=None, sales_channel='web', override_now_dt: datetime=None) -> None:
"""
Assigns addons to eligible products in a user's cart, adding and removing the addon products as necessary to
@@ -1635,6 +1635,7 @@ def set_cart_addons(self, event: Event, addons: List[dict], cart_id: str=None, l
try:
cm = CartManager(event=event, cart_id=cart_id, invoice_address=ia, sales_channel=sales_channel)
cm.set_addons(addons)
cm.add_new_items(add_to_cart_items)
cm.commit()
except LockTimeoutException:
self.retry()