def test_module(address, expected_taxes): """ Test the DefaultTaxModule. """ # Create a product shop = get_shop(prices_include_tax=False, currency='USD') product = create_product('PROD', shop=shop, default_price=1000) price = product.get_shop_instance(shop).default_price # Put the tax rules into database for ruledef in shuffled(TAX_RULE_DEFS): rule = ruledef.get_tax_rule() rule.tax.save() rule.tax = rule.tax # refresh the id rule.save() rule.tax_classes.add(product.tax_class) assert TaxRule.objects.count() == len(TAX_RULE_DEFS) with override_settings(SHOOP_TAX_MODULE='default_tax'): module = get_tax_module() assert isinstance(module, DefaultTaxModule) context = TaxingContext(location=address) taxed_price = module.get_taxed_price_for(context, product, price) expected_codes = set(sum([x.split() for x in expected_taxes], [])) assert set(x.tax.code for x in taxed_price.taxes) == expected_codes expected_tax = Money(TAX_AMOUNTS[expected_taxes], 'USD') assert taxed_price.taxful.amount == price.amount + expected_tax # Clean-up the rules TaxRule.objects.all().delete()
def get_final_lines(self, with_taxes=False): """ Get lines with processed lines added. This implementation includes the all lines returned by `get_lines` and in addition, lines from shipping and payment methods, but these lines can be extended, deleted or replaced by a subclass (by overriding `_compute_processed_lines` method) and with the `post_compute_source_lines` signal. .. note:: By default, taxes for the returned lines are not calculated when `self.calculate_taxes_automatically` is false. Pass in ``True`` to `with_taxes` argument or use `calculate_taxes` method to force tax calculation. """ lines = self._processed_lines_cache if lines is None: lines = self.__compute_lines() self._processed_lines_cache = lines if not self._taxes_calculated: tax_module = taxing.get_tax_module() if with_taxes or tax_module.calculate_taxes_automatically: self._calculate_taxes(lines, tax_module) for error_message in self.get_validation_errors(): raise ValidationError(error_message.args[0], code="invalid_order_source") return lines
def get_taxed_price(self, context, quantity=1): """ :type context: shoop.core.contexts.PriceTaxContext :rtype: shoop.core.pricing.TaxedPrice """ from shoop.core import taxing module = taxing.get_tax_module() return module.determine_product_tax(context, self)
def _make_taxed(request, item, priceful, with_taxes): """ :type request: django.http.HttpRequest :type item: shoop.core.taxing.TaxableItem :type priceful: shoop.core.pricing.Priceful :rtype: shoop.core.pricing.Priceful|None """ try: tax_amount = getattr(priceful, 'tax_amount', None) except TypeError: # e.g. shoop.core.order_creator.TaxesNotCalculated tax_amount = None if tax_amount is not None: if with_taxes: return TaxedPriceInfo( priceful.taxful_price, priceful.taxful_base_price, quantity=priceful.quantity, tax_amount=tax_amount) else: return TaxedPriceInfo( priceful.taxless_price, priceful.taxless_base_price, quantity=priceful.quantity, tax_amount=tax_amount) if not should_calculate_taxes_automatically(): return None taxmod = get_tax_module() taxctx = taxmod.get_context_from_request(request) price = taxmod.get_taxed_price_for(taxctx, item, priceful.price) base_price = taxmod.get_taxed_price_for(taxctx, item, priceful.base_price) if with_taxes: return TaxedPriceInfo( price.taxful, base_price.taxful, quantity=priceful.quantity, tax_amount=price.tax_amount) else: return TaxedPriceInfo( price.taxless, base_price.taxless, quantity=priceful.quantity, tax_amount=price.tax_amount)
def _make_taxed(request, item, priceful, with_taxes): """ :type request: django.http.HttpRequest :type item: shoop.core.taxing.TaxableItem :type priceful: shoop.core.pricing.Priceful :rtype: shoop.core.pricing.Priceful|None """ try: tax_amount = getattr(priceful, "tax_amount", None) except TypeError: # e.g. shoop.core.order_creator.TaxesNotCalculated tax_amount = None if tax_amount is not None: if with_taxes: return TaxedPriceInfo( priceful.taxful_price, priceful.taxful_base_price, quantity=priceful.quantity, tax_amount=tax_amount ) else: return TaxedPriceInfo( priceful.taxless_price, priceful.taxless_base_price, quantity=priceful.quantity, tax_amount=tax_amount ) if not should_calculate_taxes_automatically(): return None taxmod = get_tax_module() taxctx = taxmod.get_context_from_request(request) price = taxmod.get_taxed_price_for(taxctx, item, priceful.price) base_price = taxmod.get_taxed_price_for(taxctx, item, priceful.base_price) if with_taxes: return TaxedPriceInfo(price.taxful, base_price.taxful, quantity=priceful.quantity, tax_amount=price.tax_amount) else: return TaxedPriceInfo( price.taxless, base_price.taxless, quantity=priceful.quantity, tax_amount=price.tax_amount )
def _calculate_taxes(self, lines): tax_module = taxing.get_tax_module() tax_module.add_taxes(self, lines) self._taxes_calculated = True
def _compute_taxes(self, lines): tax_module = taxing.get_tax_module() for line in lines: if not line.parent_line_id: line.taxes = tax_module.get_line_taxes(line)
def from_request(cls, request): return cls(pricing_context=get_pricing_module().get_context(request), taxing_context=get_tax_module().get_context(request))
def from_request(cls, request): return cls( pricing_context=get_pricing_module().get_context_from_request(request), taxing_context=get_tax_module().get_context_from_request(request), )
def calculate_taxes_or_raise(self): if not self._taxes_calculated: tax_module = taxing.get_tax_module() if not tax_module.calculate_taxes_automatically: raise TaxesNotCalculated('Taxes are not calculated') self.calculate_taxes()