[IMP] sale,*: tooling for conversion of amounts to the SO currency
Harmonize currency conversion of unit prices: * Make sure no rounding is applied during the conversion (it'll be managed by the price_unit decimal precision and the currency rounding will only be applied by the monetary fields later in the computations). * consistent parameters for the conversion (date, company, currency). * code simplification * consistent behavior when the SO has no currency specified ... Part-of: odoo/odoo#110833
This commit is contained in:
@@ -93,15 +93,12 @@ class SaleOrderLine(models.Model):
|
||||
def _get_display_price(self):
|
||||
if self.event_booth_pending_ids and self.event_id:
|
||||
company = self.event_id.company_id or self.env.company
|
||||
currency = company.currency_id
|
||||
product = self.event_booth_pending_ids.booth_category_id.product_id
|
||||
pricelist = product.product_tmpl_id._get_contextual_pricelist()
|
||||
if pricelist.discount_policy == "with_discount":
|
||||
total_price = sum([booth.booth_category_id.price_reduce for booth in self.event_booth_pending_ids])
|
||||
else:
|
||||
total_price = sum([booth.price for booth in self.event_booth_pending_ids])
|
||||
return currency._convert(
|
||||
total_price, self.order_id.currency_id,
|
||||
self.order_id.company_id or self.env.company.id,
|
||||
self.order_id.date_order or fields.Date.today())
|
||||
|
||||
return self._convert_to_sol_currency(total_price, company.currency_id)
|
||||
return super()._get_display_price()
|
||||
|
||||
@@ -173,14 +173,10 @@ class SaleOrderLine(models.Model):
|
||||
uom=self.product_uom.id
|
||||
)
|
||||
company = event_ticket.company_id or self.env.company
|
||||
currency = company.currency_id
|
||||
pricelist = self.order_id.pricelist_id
|
||||
if pricelist.discount_policy == "with_discount":
|
||||
price = event_ticket.price_reduce
|
||||
else:
|
||||
price = event_ticket.price
|
||||
return currency._convert(
|
||||
price, self.order_id.currency_id,
|
||||
self.order_id.company_id or self.env.company.id,
|
||||
self.order_id.date_order or fields.Date.today())
|
||||
return self._convert_to_sol_currency(price, company.currency_id)
|
||||
return super()._get_display_price()
|
||||
|
||||
@@ -1149,3 +1149,28 @@ class SaleOrderLine(models.Model):
|
||||
def _is_not_sellable_line(self):
|
||||
# True if the line is a computed line (reward, delivery, ...) that user cannot add manually
|
||||
return False
|
||||
|
||||
#=== TOOLING ===#
|
||||
|
||||
def _convert_to_sol_currency(self, amount, currency):
|
||||
"""Convert the given amount from the given currency to the SO(L) currency.
|
||||
|
||||
:param float amount: the amount to convert
|
||||
:param currency: currency in which the given amount is expressed
|
||||
:type currency: `res.currency` record
|
||||
:returns: converted amount
|
||||
:rtype: float
|
||||
"""
|
||||
self.ensure_one()
|
||||
to_currency = self.currency_id or self.order_id.currency_id
|
||||
if currency and to_currency and currency != to_currency:
|
||||
conversion_date = self.order_id.date_order or fields.Date.context_today(self)
|
||||
company = self.company_id or self.order_id.company_id or self.env.company
|
||||
return currency._convert(
|
||||
from_amount=amount,
|
||||
to_currency=to_currency,
|
||||
company=company,
|
||||
date=conversion_date,
|
||||
round=False,
|
||||
)
|
||||
return amount
|
||||
|
||||
@@ -18,16 +18,8 @@ class SaleOrderLine(models.Model):
|
||||
else:
|
||||
product_cost = line.expense_id.untaxed_amount
|
||||
|
||||
from_currency = line.expense_id.currency_id
|
||||
to_currency = line.currency_id or line.order_id.currency_id
|
||||
line.purchase_price = line._convert_to_sol_currency(
|
||||
product_cost,
|
||||
line.expense_id.currency_id)
|
||||
|
||||
if to_currency and product_cost and from_currency != to_currency:
|
||||
line.purchase_price = from_currency._convert(
|
||||
from_amount=product_cost,
|
||||
to_currency=to_currency,
|
||||
company=line.company_id or self.env.company,
|
||||
date=line.order_id.date_order or date_today,
|
||||
round=False)
|
||||
else:
|
||||
line.purchase_price = product_cost
|
||||
return super(SaleOrderLine, self - expense_lines)._compute_purchase_price()
|
||||
|
||||
@@ -24,37 +24,19 @@ class SaleOrderLine(models.Model):
|
||||
line.purchase_price = 0.0
|
||||
continue
|
||||
line = line.with_company(line.company_id)
|
||||
product_cost = line.product_id.standard_price
|
||||
line.purchase_price = line._convert_price(product_cost, line.product_id.uom_id)
|
||||
|
||||
# Convert the cost to the line UoM
|
||||
product_cost = line.product_id.uom_id._compute_price(
|
||||
line.product_id.standard_price,
|
||||
line.product_uom,
|
||||
)
|
||||
|
||||
line.purchase_price = line._convert_to_sol_currency(
|
||||
product_cost,
|
||||
line.product_id.cost_currency_id)
|
||||
|
||||
@api.depends('price_subtotal', 'product_uom_qty', 'purchase_price')
|
||||
def _compute_margin(self):
|
||||
for line in self:
|
||||
line.margin = line.price_subtotal - (line.purchase_price * line.product_uom_qty)
|
||||
line.margin_percent = line.price_subtotal and line.margin/line.price_subtotal
|
||||
|
||||
def _convert_price(self, product_cost, from_uom):
|
||||
self.ensure_one()
|
||||
if not product_cost:
|
||||
# If the standard_price is 0
|
||||
# Avoid unnecessary computations
|
||||
# and currency conversions
|
||||
if not self.purchase_price:
|
||||
return product_cost
|
||||
from_currency = self.product_id.cost_currency_id
|
||||
to_cur = self.currency_id or self.order_id.currency_id
|
||||
to_uom = self.product_uom
|
||||
if to_uom and to_uom != from_uom:
|
||||
product_cost = from_uom._compute_price(
|
||||
product_cost,
|
||||
to_uom,
|
||||
)
|
||||
return from_currency._convert(
|
||||
from_amount=product_cost,
|
||||
to_currency=to_cur,
|
||||
company=self.company_id or self.env.company,
|
||||
date=self.order_id.date_order or fields.Date.today(),
|
||||
round=False,
|
||||
) if to_cur and product_cost else product_cost
|
||||
# The pricelist may not have been set, therefore no conversion
|
||||
# is needed because we don't know the target currency..
|
||||
|
||||
@@ -19,11 +19,8 @@ class SaleOrderLine(models.Model):
|
||||
if line.product_uom and line.product_uom != product.uom_id:
|
||||
purch_price = product.uom_id._compute_price(purch_price, line.product_uom)
|
||||
to_cur = line.currency_id or line.order_id.currency_id
|
||||
line.purchase_price = product.cost_currency_id._convert(
|
||||
from_amount=purch_price,
|
||||
to_currency=to_cur,
|
||||
company=line.company_id or self.env.company,
|
||||
date=line.order_id.date_order or fields.Date.today(),
|
||||
round=False,
|
||||
) if to_cur and purch_price else purch_price
|
||||
line.purchase_price = line._convert_to_sol_currency(
|
||||
purch_price,
|
||||
product.cost_currency_id,
|
||||
)
|
||||
return super(SaleOrderLine, lines_without_moves)._compute_purchase_price()
|
||||
|
||||
@@ -23,10 +23,20 @@ class SaleOrderLine(models.Model):
|
||||
for line in timesheet_sols:
|
||||
line = line.with_company(line.company_id)
|
||||
product_cost = mapped_sol_timesheet_amount.get(line.id, line.product_id.standard_price)
|
||||
if line.product_id.uom_id != line.company_id.project_time_mode_id and\
|
||||
line.product_id.uom_id.category_id.id == line.company_id.project_time_mode_id.category_id.id:
|
||||
if (
|
||||
line.product_id.uom_id != line.company_id.project_time_mode_id
|
||||
and line.product_id.uom_id.category_id.id == line.company_id.project_time_mode_id.category_id.id
|
||||
):
|
||||
product_cost = line.company_id.project_time_mode_id._compute_quantity(
|
||||
product_cost,
|
||||
line.product_id.uom_id
|
||||
)
|
||||
line.purchase_price = line._convert_price(product_cost, line.product_id.uom_id)
|
||||
|
||||
# Convert the cost to the line UoM
|
||||
product_cost = line.product_id.uom_id._compute_price(
|
||||
line.product_id.standard_price,
|
||||
line.product_uom,
|
||||
)
|
||||
|
||||
line.purchase_price = line._convert_to_sol_currency(
|
||||
product_cost, line.product_id.cost_currency_id)
|
||||
|
||||
Reference in New Issue
Block a user