[FIX] sale: Report on converted currency
Before when reporting in the sale module in a multi-company environment currencies where not converted to a unique currency before mathematical operations (sum, avg, ...). Now before mathematical operations currencies are converted to the currency of the company currently selected. Task - 2696759 closes odoo/odoo#83550 Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit is contained in:
@@ -23,7 +23,7 @@ class SaleReport(models.Model):
|
||||
)
|
||||
|
||||
def _select_pos(self):
|
||||
select_ = """
|
||||
select_ = f"""
|
||||
-MIN(l.id) AS id,
|
||||
l.product_id AS product_id,
|
||||
t.uom_id AS product_uom,
|
||||
@@ -32,10 +32,22 @@ class SaleReport(models.Model):
|
||||
0 AS qty_to_deliver,
|
||||
CASE WHEN pos.state = 'invoiced' THEN SUM(l.qty) ELSE 0 END AS qty_invoiced,
|
||||
CASE WHEN pos.state != 'invoiced' THEN SUM(l.qty) ELSE 0 END AS qty_to_invoice,
|
||||
SUM(l.price_subtotal_incl) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_total,
|
||||
SUM(l.price_subtotal) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_subtotal,
|
||||
(CASE WHEN pos.state != 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_to_invoice,
|
||||
(CASE WHEN pos.state = 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_invoiced,
|
||||
SUM(l.price_subtotal_incl)
|
||||
* MIN({self._case_value_or_one('pos.currency_rate')})
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
AS price_total,
|
||||
SUM(l.price_subtotal)
|
||||
* MIN({self._case_value_or_one('pos.currency_rate')})
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
AS price_subtotal,
|
||||
(CASE WHEN pos.state != 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END)
|
||||
* MIN({self._case_value_or_one('pos.currency_rate')})
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
AS amount_to_invoice,
|
||||
(CASE WHEN pos.state = 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END)
|
||||
* MIN({self._case_value_or_one('pos.currency_rate')})
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
AS amount_invoiced,
|
||||
count(*) AS nbr,
|
||||
pos.name AS name,
|
||||
pos.date_order AS date,
|
||||
@@ -57,7 +69,10 @@ class SaleReport(models.Model):
|
||||
(SUM(t.weight) * l.qty / u.factor) AS weight,
|
||||
(SUM(t.volume) * l.qty / u.factor) AS volume,
|
||||
l.discount AS discount,
|
||||
SUM((l.price_unit * l.discount * l.qty / 100.0 / CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END)) AS discount_amount,
|
||||
SUM((l.price_unit * l.discount * l.qty / 100.0
|
||||
* {self._case_value_or_one('pos.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}))
|
||||
AS discount_amount,
|
||||
NULL AS order_id"""
|
||||
|
||||
additional_fields_info = self._select_additional_fields()
|
||||
@@ -76,7 +91,15 @@ class SaleReport(models.Model):
|
||||
LEFT JOIN product_template t ON p.product_tmpl_id=t.id
|
||||
LEFT JOIN uom_uom u ON u.id=t.uom_id
|
||||
LEFT JOIN pos_session session ON session.id = pos.session_id
|
||||
LEFT JOIN pos_config config ON config.id = session.config_id"""
|
||||
LEFT JOIN pos_config config ON config.id = session.config_id
|
||||
JOIN {currency_table} ON currency_table.company_id = pos.company_id
|
||||
""".format(
|
||||
currency_table=self.env['res.currency']._get_query_currency_table(
|
||||
{
|
||||
'multi_company': True,
|
||||
'date': {'date_to': fields.Date.today()}
|
||||
}),
|
||||
)
|
||||
|
||||
def _where_pos(self):
|
||||
return """
|
||||
@@ -103,7 +126,8 @@ class SaleReport(models.Model):
|
||||
partner.industry_id,
|
||||
partner.commercial_partner_id,
|
||||
u.factor,
|
||||
pos.crm_team_id"""
|
||||
pos.crm_team_id,
|
||||
currency_table.rate"""
|
||||
|
||||
def _query(self):
|
||||
res = super()._query()
|
||||
|
||||
@@ -62,8 +62,8 @@ class SaleReport(models.Model):
|
||||
return ""
|
||||
|
||||
def _select_sale(self):
|
||||
select_ = """
|
||||
coalesce(min(l.id), -s.id) AS id,
|
||||
select_ = f"""
|
||||
COALESCE(min(l.id), -s.id) AS id,
|
||||
l.product_id AS product_id,
|
||||
t.uom_id AS product_uom,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS product_uom_qty,
|
||||
@@ -71,10 +71,26 @@ class SaleReport(models.Model):
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM((l.product_uom_qty - l.qty_delivered) / u.factor * u2.factor) ELSE 0 END AS qty_to_deliver,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.qty_invoiced / u.factor * u2.factor) ELSE 0 END AS qty_invoiced,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.qty_to_invoice / u.factor * u2.factor) ELSE 0 END AS qty_to_invoice,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_total / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END) ELSE 0 END AS price_total,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_subtotal / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END) ELSE 0 END AS price_subtotal,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_to_invoice / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END) ELSE 0 END AS untaxed_amount_to_invoice,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_invoiced / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END) ELSE 0 END AS untaxed_amount_invoiced,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_total
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
) ELSE 0
|
||||
END AS price_total,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_subtotal
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
) ELSE 0
|
||||
END AS price_subtotal,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_to_invoice
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
) ELSE 0
|
||||
END AS untaxed_amount_to_invoice,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_invoiced
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
) ELSE 0
|
||||
END AS untaxed_amount_invoiced,
|
||||
COUNT(*) AS nbr,
|
||||
s.name AS name,
|
||||
s.date_order AS date,
|
||||
@@ -96,7 +112,11 @@ class SaleReport(models.Model):
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(p.weight * l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS weight,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(p.volume * l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS volume,
|
||||
l.discount AS discount,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM((l.price_unit * l.product_uom_qty * l.discount / 100.0 / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END))ELSE 0 END AS discount_amount,
|
||||
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_unit * l.product_uom_qty * l.discount / 100.0
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')}
|
||||
) ELSE 0
|
||||
END AS discount_amount,
|
||||
s.id AS order_id"""
|
||||
|
||||
additional_fields_info = self._select_additional_fields()
|
||||
@@ -107,6 +127,9 @@ class SaleReport(models.Model):
|
||||
|
||||
return select_
|
||||
|
||||
def _case_value_or_one(self, value):
|
||||
return f"""CASE COALESCE({value}, 0) WHEN 0 THEN 1.0 ELSE {value} END"""
|
||||
|
||||
def _select_additional_fields(self):
|
||||
"""Hook to return additional fields SQL specification for select part of the table query.
|
||||
|
||||
@@ -123,7 +146,15 @@ class SaleReport(models.Model):
|
||||
LEFT JOIN product_product p ON l.product_id=p.id
|
||||
LEFT JOIN product_template t ON p.product_tmpl_id=t.id
|
||||
LEFT JOIN uom_uom u ON u.id=l.product_uom
|
||||
LEFT JOIN uom_uom u2 ON u2.id=t.uom_id"""
|
||||
LEFT JOIN uom_uom u2 ON u2.id=t.uom_id
|
||||
JOIN {currency_table} ON currency_table.company_id = s.company_id
|
||||
""".format(
|
||||
currency_table=self.env['res.currency']._get_query_currency_table(
|
||||
{
|
||||
'multi_company': True,
|
||||
'date': {'date_to': fields.Date.today()}
|
||||
}),
|
||||
)
|
||||
|
||||
def _where_sale(self):
|
||||
return """
|
||||
@@ -152,7 +183,8 @@ class SaleReport(models.Model):
|
||||
partner.industry_id,
|
||||
partner.commercial_partner_id,
|
||||
l.discount,
|
||||
s.id"""
|
||||
s.id,
|
||||
currency_table.rate"""
|
||||
|
||||
def _query(self):
|
||||
with_ = self._with_sale()
|
||||
@@ -165,6 +197,6 @@ class SaleReport(models.Model):
|
||||
{")" if with_ else ""}
|
||||
"""
|
||||
|
||||
def init(self):
|
||||
tools.drop_view_if_exists(self.env.cr, self._table)
|
||||
self.env.cr.execute(f"CREATE OR REPLACE VIEW {self._table} AS {self._query()}")
|
||||
@property
|
||||
def _table_query(self):
|
||||
return self._query()
|
||||
|
||||
@@ -11,5 +11,8 @@ class SaleReport(models.Model):
|
||||
|
||||
def _select_additional_fields(self):
|
||||
res = super()._select_additional_fields()
|
||||
res['margin'] = "SUM(l.margin / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END)"
|
||||
res['margin'] = f"""SUM(l.margin
|
||||
* {self._case_value_or_one('s.currency_rate')}
|
||||
* {self._case_value_or_one('currency_table.rate')})
|
||||
"""
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user