def test_quantize(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range = MoneyRange(price1, price2) result = price_range.quantize() assert str(result.start.amount) == '10.00' assert str(result.stop.amount) == '30.00'
def get_price_range(self, discounts: Iterable[DiscountInfo] = None ) -> MoneyRange: if self.variants.all(): prices = [variant.get_price(discounts) for variant in self] return MoneyRange(min(prices), max(prices)) price = calculate_discounted_price(self, self.price, discounts) return MoneyRange(start=price, stop=price)
def test_construction(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range = MoneyRange(price1, price2) assert price_range.start == price1 assert price_range.stop == price2 with pytest.raises(ValueError): MoneyRange(price1, Money(20, 'PLN')) with pytest.raises(ValueError): MoneyRange(price2, price1)
def test_replace(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price3 = Money(20, 'EUR') price_range = MoneyRange(price1, price2) result = price_range.replace(stop=price3) assert result.start == price1 assert result.stop == price3 result = price_range.replace(start=price3) assert result.start == price3 assert result.stop == price2
def test_subtraction_with_money_range(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range1 = MoneyRange(price1, price2) price3 = TaxedMoney(Money(40, 'EUR'), Money(60, 'EUR')) price4 = TaxedMoney(Money(80, 'EUR'), Money(120, 'EUR')) price_range2 = TaxedMoneyRange(price3, price4) result = price_range2 - price_range1 assert result.start == price3 - price1 assert result.stop == price4 - price2 with pytest.raises(ValueError): price_range2 - MoneyRange(Money(1, 'BTC'), Money(2, 'BTC'))
def test_addition_with_money_range(): price1 = TaxedMoney(Money(10, 'EUR'), Money(15, 'EUR')) price2 = TaxedMoney(Money(30, 'EUR'), Money(45, 'EUR')) price_range1 = TaxedMoneyRange(price1, price2) price3 = Money(40, 'EUR') price4 = Money(80, 'EUR') price_range2 = MoneyRange(price3, price4) result = price_range1 + price_range2 assert result.start == price1 + price3 assert result.stop == price2 + price4 with pytest.raises(ValueError): price_range1 + MoneyRange(Money(1, 'BTC'), Money(2, 'BTC'))
def test_comparison(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range1 = MoneyRange(price1, price2) price3 = Money(40, 'EUR') price4 = Money(80, 'EUR') price_range2 = MoneyRange(price3, price4) assert price_range1 == MoneyRange(price1, price2) assert price_range1 != price_range2 assert price_range1 != MoneyRange(price1, price1) assert price_range1 != MoneyRange( Money(10, 'USD'), Money(30, 'USD')) assert price_range1 != price1
def get_display_price(base: Union[TaxedMoney, TaxedMoneyRange], display_gross: bool = False) -> Money: """Return the price amount that should be displayed based on settings.""" if not display_gross: display_gross = display_gross_prices() if isinstance(base, TaxedMoneyRange): if display_gross: base = MoneyRange(start=base.start.gross, stop=base.stop.gross) else: base = MoneyRange(start=base.start.net, stop=base.stop.net) if isinstance(base, TaxedMoney): base = base.gross if display_gross else base.net return base
def get_product_costs_data(product): purchase_costs_range = MoneyRange(start=ZERO_MONEY, stop=ZERO_MONEY) margin = (0, 0) if not product.variants.exists(): return purchase_costs_range, margin variants = product.variants.all() costs_data = get_cost_data_from_variants(variants) if costs_data.costs: purchase_costs_range = MoneyRange(min(costs_data.costs), max(costs_data.costs)) if costs_data.margins: margin = (costs_data.margins[0], costs_data.margins[-1]) return purchase_costs_range, margin
def price(context, base, display_gross=None, html=True): if isinstance(base, (TaxedMoney, TaxedMoneyRange)): if display_gross is None: display_gross = context["site"].settings.display_gross_prices if isinstance(base, TaxedMoneyRange): if display_gross: base = MoneyRange(start=base.start.gross, stop=base.stop.gross) else: base = MoneyRange(start=base.start.net, stop=base.stop.net) if isinstance(base, TaxedMoney): base = base.gross if display_gross else base.net is_range = isinstance(base, MoneyRange) return {"price": base, "is_range": is_range, "html": html}
def get_product_price_range( *, product: Product, variants: Iterable[ProductVariant], variants_channel_listing: List[ProductVariantChannelListing], collections: Iterable[Collection], discounts: Iterable[DiscountInfo], channel: Channel, ) -> Optional[MoneyRange]: with opentracing.global_tracer().start_active_span( "get_product_price_range"): if variants: prices = [ get_variant_price( variant=variant, variant_channel_listing=variants_channel_listing[i], product=product, collections=collections, discounts=discounts, channel=channel, ) for i, variant in enumerate(variants) ] return MoneyRange(min(prices), max(prices)) return None
def price_range(self): prices = [ shipping_method.get_total() for shipping_method in self.shipping_methods.all()] if prices: return MoneyRange(min(prices).net, max(prices).net) return None
def resolve_price_range(channel_slug): # TODO: Add dataloader. channel_listing = models.ShippingMethodChannelListing.objects.filter( channel__slug=str(channel_slug)) prices = [shipping.get_total() for shipping in channel_listing] return MoneyRange(min(prices), max(prices)) if prices else None
def get_price_range( self, discounts: Optional[Iterable[DiscountInfo]] = None ) -> MoneyRange: import opentracing with opentracing.global_tracer().start_active_span("get_price_range"): if self.variants.all(): prices = [variant.get_price(discounts) for variant in self] return MoneyRange(min(prices), max(prices)) price = calculate_discounted_price( product=self, price=self.price, collections=self.collections.all(), discounts=discounts, ) return MoneyRange(start=price, stop=price)
def price(context, base, display_gross=None, html=True): if isinstance(base, (TaxedMoney, TaxedMoneyRange)): if display_gross is None: display_gross = True if isinstance(base, TaxedMoneyRange): if display_gross: base = MoneyRange(start=base.start.gross, stop=base.stop.gross) else: base = MoneyRange(start=base.start.net, stop=base.stop.net) if isinstance(base, TaxedMoney): base = base.gross if display_gross else base.net is_range = isinstance(base, MoneyRange) return {'price': base, 'is_range': is_range, 'html': html}
def get_product_price_range( *, product: Product, variants: Iterable[ProductVariant], variants_channel_listing: List[ProductVariantChannelListing], collections: Iterable[Collection], discounts: Iterable[DiscountInfo], channel: Channel, ) -> Optional[MoneyRange]: with opentracing.global_tracer().start_active_span("get_product_price_range"): if variants: variants_channel_listing_dict = { channel_listing.variant_id: channel_listing for channel_listing in variants_channel_listing if channel_listing } prices = [] for variant in variants: variant_channel_listing = variants_channel_listing_dict.get(variant.id) if variant_channel_listing: price = get_variant_price( variant=variant, variant_channel_listing=variant_channel_listing, product=product, collections=collections, discounts=discounts, channel=channel, ) prices.append(price) if prices: return MoneyRange(min(prices), max(prices)) return None
def price_range(self): prices = [ country.get_total_price() for country in self.price_per_country.all()] if prices: return MoneyRange(min(prices).net, max(prices).net) return None
def test_exchange_currency_for_money_range(): value = MoneyRange(Money(10, 'USD'), Money(15, 'USD')) value_converted = exchange_currency(value, 'GBP') assert value_converted.currency == 'GBP' assert value_converted.start == Money(40, currency='GBP') assert value_converted.stop == Money(60, currency='GBP')
def get_shipping_price_estimate( checkout: Checkout, lines: Iterable[CheckoutLine], discounts: Iterable[DiscountInfo], country_code: str, ) -> Optional[TaxedMoneyRange]: """Return the estimated price range for shipping for given order.""" shipping_methods = get_valid_shipping_methods_for_checkout( checkout, lines, discounts, country_code=country_code) if shipping_methods is None: return None # TODO: extension manager should be able to have impact on shipping price estimates min_price_amount, max_price_amount = shipping_methods.aggregate( price_amount_min=Min("price_amount"), price_amount_max=Max("price_amount")).values() if min_price_amount is None: return None manager = get_plugins_manager() prices = MoneyRange( start=Money(min_price_amount, checkout.currency), stop=Money(max_price_amount, checkout.currency), ) return manager.apply_taxes_to_shipping_price_range(prices, country_code)
def get_product_costs_data( product: "Product", ) -> Tuple[MoneyRange, Tuple[float, float]]: purchase_costs_range = MoneyRange(start=zero_money(), stop=zero_money()) margin = (0, 0) if not product.variants.exists(): return purchase_costs_range, margin variants = product.variants.all() costs_data = get_cost_data_from_variants(variants) if costs_data.costs: purchase_costs_range = MoneyRange(min(costs_data.costs), max(costs_data.costs)) if costs_data.margins: margin = (costs_data.margins[0], costs_data.margins[-1]) return purchase_costs_range, margin
def price_range(self): prices = [ delivery_method.get_total() for delivery_method in self.delivery_methods.all() ] if prices: return MoneyRange(min(prices).net, max(prices).net) return None
def test_apply_tax_to_price_no_taxes_return_taxed_money_range(): money_range = MoneyRange(Money(100, "USD"), Money(200, "USD")) taxed_money_range = TaxedMoneyRange( TaxedMoney(net=Money(100, "USD"), gross=Money(100, "USD")), TaxedMoney(net=Money(200, "USD"), gross=Money(200, "USD")), ) assert apply_tax_to_price(None, "standard", money_range) == taxed_money_range assert apply_tax_to_price(None, "standard", taxed_money_range) == taxed_money_range
def test_product_get_price_range_no_variants(product_type, category): product = models.Product.objects.create(product_type=product_type, category=category, price=Money("10.00", "MXN")) price = product.get_price_range() expected_price = Money("10.00", "MXN") assert price == MoneyRange(start=expected_price, stop=expected_price)
def test_apply_tax_to_price_no_taxes_return_taxed_money_range(): money_range = MoneyRange(Money(100, 'USD'), Money(200, 'USD')) taxed_money_range = TaxedMoneyRange( TaxedMoney(net=Money(100, 'USD'), gross=Money(100, 'USD')), TaxedMoney(net=Money(200, 'USD'), gross=Money(200, 'USD'))) assert (apply_tax_to_price(None, 'standard', money_range) == taxed_money_range) assert (apply_tax_to_price(None, 'standard', taxed_money_range) == taxed_money_range)
def test_membership(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range = MoneyRange(price1, price2) assert price1 in price_range assert price2 in price_range assert (price1 + price2) / 2 in price_range assert price1 + price2 not in price_range with pytest.raises(TypeError): 15 in price_range
def test_addition_with_money(): price1 = Money(10, 'EUR') price2 = Money(30, 'EUR') price_range = MoneyRange(price1, price2) price3 = Money(40, 'EUR') result = price_range + price3 assert result.start == price1 + price3 assert result.stop == price2 + price3 with pytest.raises(ValueError): price_range + Money(1, 'BTC')
def test_exchange_currency_for_money_range_uses_passed_conversion_rate(): value = MoneyRange(Money(10, 'USD'), Money(15, 'USD')) custom_rate = Decimal(2) value_converted = exchange_currency(value, 'GBP', conversion_rate=custom_rate) assert value_converted.currency == 'GBP' assert value_converted.start == Money(20, currency='GBP') assert value_converted.stop == Money(30, currency='GBP')
def test_subtraction_with_money(): price1 = Money(40, 'EUR') price2 = Money(80, 'EUR') price_range = MoneyRange(price1, price2) price3 = Money(10, 'EUR') result = price_range - price3 assert result.start == price1 - price3 assert result.stop == price2 - price3 with pytest.raises(ValueError): price_range - Money(1, 'BTC')
def get_product_costs_data( variant_channel_listings: Iterable[ProductVariantChannelListing], has_variants: bool, currency: str, ) -> Tuple[MoneyRange, Tuple[float, float]]: purchase_costs_range = MoneyRange( start=zero_money(currency), stop=zero_money(currency) ) margin = (0.0, 0.0) if not has_variants: return purchase_costs_range, margin costs_data = get_cost_data_from_variant_channel_listing(variant_channel_listings) if costs_data.costs: purchase_costs_range = MoneyRange(min(costs_data.costs), max(costs_data.costs)) if costs_data.margins: margin = (costs_data.margins[0], costs_data.margins[-1]) return purchase_costs_range, margin
def test_range(): price_range = MoneyRange(Money(10, 'BTC'), Money(20, 'BTC')) result = flat_tax(price_range, 1) assert result.start == TaxedMoney(Money(10, 'BTC'), Money(20, 'BTC')) assert result.stop == TaxedMoney(Money(20, 'BTC'), Money(40, 'BTC')) price_range = TaxedMoneyRange( TaxedMoney(Money(10, 'BTC'), Money(10, 'BTC')), TaxedMoney(Money(20, 'BTC'), Money(20, 'BTC'))) result = flat_tax(price_range, 1) assert result.start == TaxedMoney(Money(10, 'BTC'), Money(20, 'BTC')) assert result.stop == TaxedMoney(Money(20, 'BTC'), Money(40, 'BTC'))