[IMP] account: split _get_tax_included_unit_price_from_price util
separate the true computation of the tax value from the computation of the base unit price (uom & curr conversion, ...). That way, the risks of unwanted side-effects is reduced when the base unit price is already computed (sale, website_sale). Also allows preprocessing the taxes mapping, which doesn't have to be done multiple times when we compute different amounts for the same product/template. original commit: bc79770d1e00cf86a46002d633afd8b32921610b Part-of: odoo/odoo#160198
This commit is contained in:
@@ -149,9 +149,9 @@ class ProductProduct(models.Model):
|
||||
return self.product_tmpl_id._get_product_accounts()
|
||||
|
||||
def _get_tax_included_unit_price(self, company, currency, document_date, document_type,
|
||||
is_refund_document=False, product_uom=None, product_currency=None,
|
||||
product_price_unit=None, product_taxes=None, fiscal_position=None
|
||||
):
|
||||
is_refund_document=False, product_uom=None, product_currency=None,
|
||||
product_price_unit=None, product_taxes=None, fiscal_position=None
|
||||
):
|
||||
""" Helper to get the price unit from different models.
|
||||
This is needed to compute the same unit price in different models (sale order, account move, etc.) with same parameters.
|
||||
"""
|
||||
@@ -187,34 +187,13 @@ class ProductProduct(models.Model):
|
||||
|
||||
# Apply fiscal position.
|
||||
if product_taxes and fiscal_position:
|
||||
product_taxes_after_fp = fiscal_position.map_tax(product_taxes)
|
||||
flattened_taxes_after_fp = product_taxes_after_fp._origin.flatten_taxes_hierarchy()
|
||||
flattened_taxes_before_fp = product_taxes._origin.flatten_taxes_hierarchy()
|
||||
taxes_before_included = all(tax.price_include for tax in flattened_taxes_before_fp)
|
||||
|
||||
if set(product_taxes.ids) != set(product_taxes_after_fp.ids) and taxes_before_included:
|
||||
taxes_res = flattened_taxes_before_fp.with_context(round=False, round_base=False).compute_all(
|
||||
product_price_unit,
|
||||
quantity=1.0,
|
||||
currency=currency,
|
||||
product=product,
|
||||
is_refund=is_refund_document,
|
||||
)
|
||||
product_price_unit = taxes_res['total_excluded']
|
||||
|
||||
if any(tax.price_include for tax in flattened_taxes_after_fp):
|
||||
taxes_res = flattened_taxes_after_fp.with_context(round=False, round_base=False).compute_all(
|
||||
product_price_unit,
|
||||
quantity=1.0,
|
||||
currency=currency,
|
||||
product=product,
|
||||
is_refund=is_refund_document,
|
||||
handle_price_include=False,
|
||||
)
|
||||
for tax_res in taxes_res['taxes']:
|
||||
tax = self.env['account.tax'].browse(tax_res['id'])
|
||||
if tax.price_include:
|
||||
product_price_unit += tax_res['amount']
|
||||
product_price_unit = self._get_tax_included_unit_price_from_price(
|
||||
product_price_unit,
|
||||
currency,
|
||||
product_taxes,
|
||||
fiscal_position=fiscal_position,
|
||||
is_refund_document=is_refund_document,
|
||||
)
|
||||
|
||||
# Apply currency rate.
|
||||
if currency != product_currency:
|
||||
@@ -222,6 +201,52 @@ class ProductProduct(models.Model):
|
||||
|
||||
return product_price_unit
|
||||
|
||||
@api.model # the product is optional for `compute_all`
|
||||
def _get_tax_included_unit_price_from_price(
|
||||
self, product_price_unit, currency, product_taxes,
|
||||
fiscal_position=None,
|
||||
product_taxes_after_fp=None,
|
||||
is_refund_document=False,
|
||||
):
|
||||
if not product_taxes:
|
||||
return product_price_unit
|
||||
|
||||
if product_taxes_after_fp is None:
|
||||
if not fiscal_position:
|
||||
return product_price_unit
|
||||
|
||||
product_taxes_after_fp = fiscal_position.map_tax(product_taxes)
|
||||
|
||||
flattened_taxes_after_fp = product_taxes_after_fp._origin.flatten_taxes_hierarchy()
|
||||
flattened_taxes_before_fp = product_taxes._origin.flatten_taxes_hierarchy()
|
||||
taxes_before_included = all(tax.price_include for tax in flattened_taxes_before_fp)
|
||||
|
||||
if set(product_taxes.ids) != set(product_taxes_after_fp.ids) and taxes_before_included:
|
||||
taxes_res = flattened_taxes_before_fp.with_context(round=False, round_base=False).compute_all(
|
||||
product_price_unit,
|
||||
quantity=1.0,
|
||||
currency=currency,
|
||||
product=self,
|
||||
is_refund=is_refund_document,
|
||||
)
|
||||
product_price_unit = taxes_res['total_excluded']
|
||||
|
||||
if any(tax.price_include for tax in flattened_taxes_after_fp):
|
||||
taxes_res = flattened_taxes_after_fp.with_context(round=False, round_base=False).compute_all(
|
||||
product_price_unit,
|
||||
quantity=1.0,
|
||||
currency=currency,
|
||||
product=self,
|
||||
is_refund=is_refund_document,
|
||||
handle_price_include=False,
|
||||
)
|
||||
for tax_res in taxes_res['taxes']:
|
||||
tax = self.env['account.tax'].browse(tax_res['id'])
|
||||
if tax.price_include:
|
||||
product_price_unit += tax_res['amount']
|
||||
|
||||
return product_price_unit
|
||||
|
||||
@api.depends('lst_price', 'product_tmpl_id', 'taxes_id')
|
||||
def _compute_tax_string(self):
|
||||
for record in self:
|
||||
|
||||
@@ -471,14 +471,13 @@ class SaleOrderLine(models.Model):
|
||||
else:
|
||||
line = line.with_company(line.company_id)
|
||||
price = line._get_display_price()
|
||||
line.price_unit = line.product_id._get_tax_included_unit_price(
|
||||
line.company_id or line.env.company,
|
||||
line.order_id.currency_id,
|
||||
line.order_id.date_order,
|
||||
'sale',
|
||||
line.price_unit = line.product_id._get_tax_included_unit_price_from_price(
|
||||
price,
|
||||
line.currency_id or line.order_id.currency_id,
|
||||
product_taxes=line.product_id.taxes_id.filtered(
|
||||
lambda tax: tax.company_id == line.env.company
|
||||
),
|
||||
fiscal_position=line.order_id.fiscal_position_id,
|
||||
product_price_unit=price,
|
||||
product_currency=line.currency_id
|
||||
)
|
||||
|
||||
def _get_display_price(self):
|
||||
|
||||
Reference in New Issue
Block a user