forked from CGM_Public/pretix_original
first round of cleanup
This commit is contained in:
@@ -42,6 +42,7 @@ LINE_PRICE_GROSS = 2
|
||||
IS_ADDON_TO = 3
|
||||
VOUCHER_DISCOUNT = 4
|
||||
|
||||
|
||||
class Discount(LoggedModel):
|
||||
SUBEVENT_MODE_MIXED = 'mixed'
|
||||
SUBEVENT_MODE_SAME = 'same'
|
||||
@@ -280,30 +281,39 @@ class Discount(LoggedModel):
|
||||
if not self.condition_min_count:
|
||||
raise ValueError('Validation invariant violated.')
|
||||
|
||||
condition_idx_group = sorted(condition_idx_group, key=lambda idx: (positions[idx][LINE_PRICE_GROSS], -idx)) # sort by line_price
|
||||
benefit_idx_group = sorted(benefit_idx_group, key=lambda idx: (positions[idx][LINE_PRICE_GROSS], -idx)) # sort by line_price
|
||||
# sort by line_price
|
||||
condition_idx_group = sorted(condition_idx_group, key=lambda idx: (positions[idx][LINE_PRICE_GROSS], -idx))
|
||||
benefit_idx_group = sorted(benefit_idx_group, key=lambda idx: (positions[idx][LINE_PRICE_GROSS], -idx))
|
||||
|
||||
# Prevent over-consuming of items, i.e. if our discount is "buy 2, get 1 free", we only
|
||||
# want to match multiples of 3
|
||||
possible_applications_cond = len(condition_idx_group) // self.condition_min_count # how many discount applications are allowed according to condition products in cart
|
||||
possible_applications_benefit = ceil(len(benefit_idx_group) / self.benefit_only_apply_to_cheapest_n_matches) # how many discount applications are possible according to benefitting products in cart
|
||||
|
||||
# how many discount applications are allowed according to condition products in cart
|
||||
possible_applications_cond = len(condition_idx_group) // self.condition_min_count
|
||||
|
||||
# how many discount applications are possible according to benefitting products in cart
|
||||
possible_applications_benefit = ceil(len(benefit_idx_group) / self.benefit_only_apply_to_cheapest_n_matches)
|
||||
|
||||
n_groups = min(possible_applications_cond, possible_applications_benefit)
|
||||
consume_idx = condition_idx_group[:n_groups * self.condition_min_count]
|
||||
benefit_idx = benefit_idx_group[:n_groups * self.benefit_only_apply_to_cheapest_n_matches]
|
||||
|
||||
if collect_potential_discounts is not None and n_groups * self.benefit_only_apply_to_cheapest_n_matches > len(
|
||||
benefit_idx_group):
|
||||
# "angebrochener" discount ("for each 1 ticket you buy, get 50% on 2 t-shirts", cart content: 1 ticket but only 1 t-shirt) -> 1 shirt definitiv potential discount
|
||||
for idx in consume_idx:
|
||||
collect_potential_discounts[idx] = [(self, n_groups * self.benefit_only_apply_to_cheapest_n_matches - len(benefit_idx_group), -1)]
|
||||
if collect_potential_discounts is not None:
|
||||
if n_groups * self.benefit_only_apply_to_cheapest_n_matches > len(benefit_idx_group):
|
||||
# "angebrochener" discount ("for each 1 ticket you buy, get 50% on 2 t-shirts", cart content: 1 ticket
|
||||
# but only 1 t-shirt) -> 1 shirt definitiv potential discount
|
||||
for idx in consume_idx:
|
||||
collect_potential_discounts[idx] = [
|
||||
(self, n_groups * self.benefit_only_apply_to_cheapest_n_matches - len(benefit_idx_group), -1)
|
||||
]
|
||||
|
||||
if collect_potential_discounts is not None and possible_applications_cond * self.benefit_only_apply_to_cheapest_n_matches > len(
|
||||
benefit_idx_group):
|
||||
# "ungenutzter" discount ("for each 1 ticket you buy, get 50% on 2 t-shirts", cart content: 1 ticket but 0 t-shirts) -> 2 shirt maybe potential discount (if the 1 ticket is not consumed by a later discount)
|
||||
for i, idx in enumerate(condition_idx_group[n_groups * self.condition_min_count:]):
|
||||
collect_potential_discounts[idx] += [
|
||||
(self, self.benefit_only_apply_to_cheapest_n_matches, i // self.condition_min_count)
|
||||
]
|
||||
if possible_applications_cond * self.benefit_only_apply_to_cheapest_n_matches > len(benefit_idx_group):
|
||||
# "ungenutzter" discount ("for each 1 ticket you buy, get 50% on 2 t-shirts", cart content: 1 ticket
|
||||
# but 0 t-shirts) -> 2 shirt maybe potential discount (if the 1 ticket is not consumed by a later discount)
|
||||
for i, idx in enumerate(condition_idx_group[n_groups * self.condition_min_count:]):
|
||||
collect_potential_discounts[idx] += [
|
||||
(self, self.benefit_only_apply_to_cheapest_n_matches, i // self.condition_min_count)
|
||||
]
|
||||
|
||||
else:
|
||||
consume_idx = condition_idx_group
|
||||
@@ -324,7 +334,8 @@ class Discount(LoggedModel):
|
||||
for idx in consume_idx:
|
||||
result.setdefault(idx, positions[idx][LINE_PRICE_GROSS])
|
||||
|
||||
def apply(self, positions: Dict[int, Tuple[int, Optional[int], Decimal, bool, Decimal]], collect_potential_discounts=None) -> Dict[int, Decimal]:
|
||||
def apply(self, positions: Dict[int, Tuple[int, Optional[int], Decimal, bool, Decimal]],
|
||||
collect_potential_discounts=None) -> Dict[int, Decimal]:
|
||||
"""
|
||||
Tries to apply this discount to a cart
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ class ItemCategory(LoggedModel):
|
||||
cross_selling_mode = models.CharField(
|
||||
choices=CROSS_SELLING_MODES,
|
||||
null=True,
|
||||
max_length=5
|
||||
)
|
||||
CROSS_SELLING_CONDITION = (
|
||||
('always', _('Always show in cross-selling step')),
|
||||
@@ -131,6 +132,7 @@ class ItemCategory(LoggedModel):
|
||||
verbose_name=_("Cross-selling condition"),
|
||||
choices=CROSS_SELLING_CONDITION,
|
||||
null=True,
|
||||
max_length=10,
|
||||
)
|
||||
cross_selling_match_products = models.ManyToManyField(
|
||||
'pretixbase.Item',
|
||||
@@ -158,15 +160,13 @@ class ItemCategory(LoggedModel):
|
||||
if self.cross_selling_condition == 'always':
|
||||
return self.items.all(), {}
|
||||
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 (self.items.all(), {}) if any(pos.item.pk in match for pos in cart) else ([], {})
|
||||
if self.cross_selling_condition == 'discounts':
|
||||
# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrgggghhhhhh
|
||||
potential_discounts_dict = defaultdict(list)
|
||||
|
||||
from ..services.pricing import apply_discounts
|
||||
|
||||
potential_discounts_dict = defaultdict(list)
|
||||
discount_results = apply_discounts(
|
||||
apply_discounts(
|
||||
self.event,
|
||||
sales_channel,
|
||||
[
|
||||
@@ -176,7 +176,6 @@ class ItemCategory(LoggedModel):
|
||||
],
|
||||
collect_potential_discounts=potential_discounts_dict
|
||||
)
|
||||
print("potential_discounts_dict", potential_discounts_dict)
|
||||
potential_discount_infos = dict.fromkeys(info for lst in potential_discounts_dict.values() for info in lst)
|
||||
|
||||
# sum up the max_counts and pass them on (also pass on the discount_rules so we can calculate actual discounted prices later):
|
||||
@@ -199,15 +198,18 @@ class ItemCategory(LoggedModel):
|
||||
]
|
||||
|
||||
def sum_or_none(iter):
|
||||
return functools.reduce(lambda x,y: None if x is None or y is None else x + y, iter, 0)
|
||||
return functools.reduce(lambda x, y: None if x is None or y is None else x + y, iter, 0)
|
||||
|
||||
my_item_pks = self.items.values_list('pk', flat=True)
|
||||
print("grouped:",grouped_by_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
|
||||
if item.pk in my_item_pks}
|
||||
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
|
||||
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()}
|
||||
return self.items.filter(pk__in=potential_discount_items), potential_discount_items
|
||||
|
||||
def __str__(self):
|
||||
|
||||
Reference in New Issue
Block a user