mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
display discounted prices, limit number of products according to discount rule
This commit is contained in:
@@ -149,17 +149,17 @@ class ItemCategory(LoggedModel):
|
|||||||
If this category should be visible in the cross-selling step for a given cart and sales_channel, this method
|
If this category should be visible in the cross-selling step for a given cart and sales_channel, this method
|
||||||
returns a dict describing the items that should be displayed.
|
returns a dict describing the items that should be displayed.
|
||||||
|
|
||||||
:returns: dict {item: (max_count, discount_rule)}
|
:returns: (QuerySet<Item>, dict<item_pk: (max_count, discount_rule)>)
|
||||||
max_count is None if the item should not be limited
|
max_count is None if the item should not be limited
|
||||||
discount_rule is None if the item will not be discounted
|
discount_rule is None if the item will not be discounted
|
||||||
"""
|
"""
|
||||||
if self.cross_selling_mode is None:
|
if self.cross_selling_mode is None:
|
||||||
return []
|
return [], {}
|
||||||
if self.cross_selling_condition == 'always':
|
if self.cross_selling_condition == 'always':
|
||||||
return {item: (None, None) for item in self.items.all()}
|
return self.items.all(), {}
|
||||||
if self.cross_selling_condition == 'products':
|
if self.cross_selling_condition == 'products':
|
||||||
match = set(match.pk for match in self.cross_selling_match_products.only('pk')) # TODO prefetch this
|
match = set(match.pk for match in self.cross_selling_match_products.only('pk')) # TODO prefetch this
|
||||||
return {item: (None, None) for item in self.items.all()} if any(pos.item.pk in match for pos in cart) else []
|
return (self.items.all(), {}) if any(pos.item.pk in match for pos in cart) else ([], {})
|
||||||
if self.cross_selling_condition == 'discounts':
|
if self.cross_selling_condition == 'discounts':
|
||||||
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrgggghhhhhh
|
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrgggghhhhhh
|
||||||
|
|
||||||
@@ -203,12 +203,12 @@ class ItemCategory(LoggedModel):
|
|||||||
|
|
||||||
my_item_pks = self.items.values_list('pk', flat=True)
|
my_item_pks = self.items.values_list('pk', flat=True)
|
||||||
print("grouped:",grouped_by_item)
|
print("grouped:",grouped_by_item)
|
||||||
potential_discount_items = {item: (sum_or_none(max_count for (item, discount_rule, max_count, i) in infos_for_item), next(discount_rule for (item, discount_rule, max_count, i) in infos_for_item))
|
potential_discount_items = {item.pk: (sum_or_none(max_count for (item, discount_rule, max_count, i) in infos_for_item), next(discount_rule for (item, discount_rule, max_count, i) in infos_for_item))
|
||||||
for item, infos_for_item in grouped_by_item
|
for item, infos_for_item in grouped_by_item
|
||||||
if item.pk in my_item_pks}
|
if item.pk in my_item_pks}
|
||||||
|
|
||||||
#potential_discount_items = {item.pk for (discount_rule, max_count, i) in potential_discount_infos.keys() for item in discount_rule.benefit_limit_products.all()}
|
#potential_discount_items = {item.pk for (discount_rule, max_count, i) in potential_discount_infos.keys() for item in discount_rule.benefit_limit_products.all()}
|
||||||
return potential_discount_items
|
return self.items.filter(pk__in=potential_discount_items), potential_discount_items
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
name = self.internal_name or self.name
|
name = self.internal_name or self.name
|
||||||
|
|||||||
@@ -499,12 +499,12 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
def cross_selling_applicable_categories(self):
|
def cross_selling_applicable_categories(self):
|
||||||
cart = get_cart(self.request)
|
cart = get_cart(self.request)
|
||||||
return [
|
return [
|
||||||
(c, products) for (c, products) in
|
(c, products_qs, discount_info) for (c, products_qs, discount_info) in
|
||||||
(
|
(
|
||||||
(c, c.cross_sell_visible(cart, self.request.sales_channel.identifier))
|
(c, *c.cross_sell_visible(cart, self.request.sales_channel.identifier))
|
||||||
for c in self.request.event.categories.filter(cross_selling_mode__isnull=False)
|
for c in self.request.event.categories.filter(cross_selling_mode__isnull=False)
|
||||||
)
|
)
|
||||||
if len(products) > 0
|
if len(products_qs) > 0
|
||||||
]
|
]
|
||||||
|
|
||||||
def is_completed(self, request, warn=False):
|
def is_completed(self, request, warn=False):
|
||||||
@@ -630,23 +630,23 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
|
|
||||||
if self.event.has_subevents:
|
if self.event.has_subevents:
|
||||||
return [
|
return [
|
||||||
(DummyCategory(category, subevent), self._items_for_cross_selling(subevent, items), f'subevent_{subevent.pk}_')
|
(DummyCategory(category, subevent), self._items_for_cross_selling(subevent, items_qs, discount_info), f'subevent_{subevent.pk}_')
|
||||||
for (category, items) in self.cross_selling_applicable_categories
|
for (category, items_qs, discount_info) in self.cross_selling_applicable_categories
|
||||||
for subevent in set(pos.subevent for pos in ctx['cart']['positions'])
|
for subevent in set(pos.subevent for pos in ctx['cart']['positions'])
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
return [
|
return [
|
||||||
(category, self._items_for_cross_selling(None, items))
|
(category, self._items_for_cross_selling(None, items_qs, discount_info))
|
||||||
for (category, items) in self.cross_selling_applicable_categories
|
for (category, items_qs, discount_info) in self.cross_selling_applicable_categories
|
||||||
]
|
]
|
||||||
|
|
||||||
def _items_for_cross_selling(self, subevent, cross_sell_item_info):
|
def _items_for_cross_selling(self, subevent, items_qs, discount_info):
|
||||||
items, _btn = get_grouped_items(
|
items, _btn = get_grouped_items(
|
||||||
self.request.event,
|
self.request.event,
|
||||||
subevent=subevent,
|
subevent=subevent,
|
||||||
voucher=None,
|
voucher=None,
|
||||||
channel=self.request.sales_channel.identifier,
|
channel=self.request.sales_channel.identifier,
|
||||||
base_qs=cross_sell_item_info.keys(),
|
base_qs=items_qs,
|
||||||
allow_addons=True,
|
allow_addons=True,
|
||||||
allow_cross_sell=True,
|
allow_cross_sell=True,
|
||||||
memberships=(
|
memberships=(
|
||||||
@@ -659,21 +659,22 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
(max_count, discount_rule) = cross_sell_item_info[item]
|
print("-> discount info: ",item, discount_info.get(item.pk))
|
||||||
|
if item.pk in discount_info:
|
||||||
|
(max_count, discount_rule) = discount_info[item.pk]
|
||||||
|
|
||||||
# set item.order_max for benefit_only_apply_to_cheapest_n_matches discounted items
|
# set item.order_max for benefit_only_apply_to_cheapest_n_matches discounted items
|
||||||
if max_count:
|
if max_count:
|
||||||
item.order_max = min(item.order_max, max_count)
|
item.order_max = min(item.order_max, max_count)
|
||||||
|
|
||||||
# calculate discounted price
|
# calculate discounted price
|
||||||
if discount_rule:
|
if discount_rule:
|
||||||
item.original_price = item.original_price or item.display_price
|
item.original_price = item.original_price or item.display_price
|
||||||
previous_price = item.display_price
|
previous_price = item.display_price
|
||||||
new_price = round_decimal(
|
new_price = (
|
||||||
previous_price * (Decimal('100.00') - discount_rule.benefit_discount_matching_percent) / Decimal('100.00'),
|
previous_price * ((Decimal('100.00') - discount_rule.benefit_discount_matching_percent) / Decimal('100.00'))
|
||||||
self.event.currency,
|
)
|
||||||
)
|
item.display_price = new_price
|
||||||
item.display_price = new_price
|
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user