def consume_items(self, offer, basket, affected_lines): """ Marks items within the basket lines as consumed so they can't be reused in other offers. We allow lines to be passed in as sometimes we want them sorted in a specific order. """ # Determine value of items already consumed as part of discount value_consumed = D('0.00') for line, __, qty in affected_lines: price = utils.unit_price(offer, line) value_consumed += price * qty to_consume = max(0, self.value - value_consumed) if to_consume == 0: return for price, line in self.get_applicable_lines( offer, basket, most_expensive_first=True): quantity_to_consume = min( line.quantity_without_offer_discount(offer), (to_consume / price).quantize(D(1), ROUND_UP)) line.consume(quantity_to_consume, offer=offer) to_consume -= price * quantity_to_consume if to_consume <= 0: break
def get_applicable_lines(self, offer, basket, range=None): """ Return the basket lines that are available to be discounted :basket: The basket :range: The range of products to use for filtering. The fixed-price benefit ignores its range and uses the condition range """ if range is None: range = self.range line_tuples = [] for line in basket.all_lines(): product = line.product if (not range.contains(product) or not self.can_apply_benefit(line)): continue price = utils.unit_price(offer, line) if not price: # Avoid zero price products continue if line.quantity_without_discount == 0: continue line_tuples.append((price, line)) # We sort lines to be cheapest first to ensure consistent applications return sorted(line_tuples, key=operator.itemgetter(0))
def consume_items(self, offer, basket, affected_lines): """ Marks items within the basket lines as consumed so they can't be reused in other offers. We allow lines to be passed in as sometimes we want them sorted in a specific order. """ # Determine value of items already consumed as part of discount value_consumed = D('0.00') for line, __, qty in affected_lines: price = utils.unit_price(offer, line) value_consumed += price * qty to_consume = max(0, self.value - value_consumed) if to_consume == 0: return for price, line in self.get_applicable_lines( offer, basket, most_expensive_first=True): quantity_to_consume = min( line.quantity_without_discount, (to_consume / price).quantize(D(1), ROUND_UP)) line.consume(quantity_to_consume) to_consume -= price * quantity_to_consume if to_consume <= 0: break
def get_applicable_lines(self, offer, basket, range=None): """ Return the basket lines that are available to be discounted :basket: The basket :range: The range of products to use for filtering. The fixed-price benefit ignores its range and uses the condition range """ if range is None: range = self.range line_tuples = [] for line in basket.all_lines(): product = line.product if (not range.contains(product) or not self.can_apply_benefit(line)): continue price = utils.unit_price(offer, line) if not price: # Avoid zero price products continue if line.quantity_without_offer_discount(offer) == 0: continue line_tuples.append((price, line)) # We sort lines to be cheapest first to ensure consistent applications return sorted(line_tuples, key=operator.itemgetter(0))
def _get_value_of_matches(self, offer, basket): if hasattr(self, "_value_of_matches"): return getattr(self, "_value_of_matches") value_of_matches = D("0.00") for line in basket.all_lines(): if self.can_apply_condition(line) and line.quantity_without_discount > 0: price = utils.unit_price(offer, line) value_of_matches += price * int(line.quantity_without_discount) self._value_of_matches = value_of_matches return value_of_matches
def get_value_of_satisfying_items(self, offer, basket): covered_ids = [] value = D("0.00") for line in basket.all_lines(): if self.can_apply_condition(line) and line.product.id not in covered_ids: covered_ids.append(line.product.id) value += utils.unit_price(offer, line) if len(covered_ids) >= self.value: return value return value
def get_value_of_satisfying_items(self, offer, basket): covered_ids = [] value = D('0.00') for line in basket.all_lines(): if (self.can_apply_condition(line) and line.product.id not in covered_ids): covered_ids.append(line.product.id) value += utils.unit_price(offer, line) if len(covered_ids) >= self.value: return value return value
def _get_value_of_matches(self, offer, basket): if hasattr(self, '_value_of_matches'): return getattr(self, '_value_of_matches') value_of_matches = D('0.00') for line in basket.all_lines(): if (self.can_apply_condition(line) and line.quantity_without_discount > 0): price = utils.unit_price(offer, line) value_of_matches += price * int(line.quantity_without_discount) self._value_of_matches = value_of_matches return value_of_matches
def is_satisfied(self, offer, basket): """ Determine whether a given basket meets this condition """ value_of_matches = D('0.00') for line in basket.all_lines(): if (self.can_apply_condition(line) and line.quantity_without_discount > 0): price = utils.unit_price(offer, line) value_of_matches += price * int(line.quantity_without_discount) return value_of_matches <= self.value
def is_satisfied(self, offer, basket): """ Determine whether a given basket meets this condition """ value_of_matches = D("0.00") for line in basket.all_lines(): if self.can_apply_condition(line) and line.quantity_without_discount > 0: price = utils.unit_price(offer, line) value_of_matches += price * int(line.quantity_without_discount) if value_of_matches >= self.value: return True return False
def get_applicable_lines(self, offer, basket, most_expensive_first=True): """ Return line data for the lines that can be consumed by this condition. """ line_tuples = [] for line in basket.all_lines(): if not self.can_apply_condition(line): continue price = oscar_utils.unit_price(offer, line) if not price: continue line_tuples.append((price, line)) return sorted(line_tuples, reverse=most_expensive_first, key=operator.itemgetter(0))
def _get_value_of_matches(self, offer, basket): if hasattr(self, '_value_of_matches'): return getattr(self, '_value_of_matches') value_of_matches = D('0.00') for line in basket.all_lines(): if (self.can_apply_condition(line) and line.quantity_without_offer_discount(offer) > 0): price = utils.unit_price(offer, line) value_of_matches += price * int( line.quantity_without_offer_discount(offer) ) self._value_of_matches = value_of_matches return value_of_matches
def get_applicable_lines(self, offer, basket, most_expensive_first=True): """ Return line data for the lines that can be consumed by this condition """ line_tuples = [] for line in basket.all_lines(): if not self.can_apply_condition(line): continue price = utils.unit_price(offer, line) if not price: continue line_tuples.append((price, line)) key = operator.itemgetter(0) if most_expensive_first: return sorted(line_tuples, reverse=True, key=key) return sorted(line_tuples, key=key)
def _get_unit_price(self, offer, line): price = utils.unit_price(offer, line) if self._tax_inclusive and line.is_tax_known: price += line.unit_tax return price