150 lines
5.5 KiB
Python
150 lines
5.5 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
from odoo import api, fields, models
|
||
|
|
||
|
|
||
|
class SaleReport(models.Model):
|
||
|
_inherit = "sale.report"
|
||
|
|
||
|
@api.model
|
||
|
def _get_done_states(self):
|
||
|
done_states = super()._get_done_states()
|
||
|
done_states.extend(['paid', 'pos_done', 'invoiced'])
|
||
|
return done_states
|
||
|
|
||
|
state = fields.Selection(
|
||
|
selection_add=[
|
||
|
('pos_draft', 'New'),
|
||
|
('paid', 'Paid'),
|
||
|
('pos_done', 'Posted'),
|
||
|
('invoiced', 'Invoiced')
|
||
|
],
|
||
|
)
|
||
|
|
||
|
def _select_pos(self):
|
||
|
select_ = f"""
|
||
|
-MIN(l.id) AS id,
|
||
|
l.product_id AS product_id,
|
||
|
t.uom_id AS product_uom,
|
||
|
SUM(l.qty) AS product_uom_qty,
|
||
|
SUM(l.qty) AS qty_delivered,
|
||
|
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({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) 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) 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,
|
||
|
CASE WHEN pos.state = 'draft' THEN 'pos_draft' WHEN pos.state = 'done' THEN 'pos_done' else pos.state END AS state,
|
||
|
pos.partner_id AS partner_id,
|
||
|
pos.user_id AS user_id,
|
||
|
pos.company_id AS company_id,
|
||
|
NULL AS campaign_id,
|
||
|
NULL AS medium_id,
|
||
|
NULL AS source_id,
|
||
|
t.categ_id AS categ_id,
|
||
|
pos.pricelist_id AS pricelist_id,
|
||
|
NULL AS analytic_account_id,
|
||
|
pos.crm_team_id AS team_id,
|
||
|
p.product_tmpl_id,
|
||
|
partner.country_id AS country_id,
|
||
|
partner.industry_id AS industry_id,
|
||
|
partner.commercial_partner_id AS commercial_partner_id,
|
||
|
(SUM(p.weight) * l.qty / u.factor) AS weight,
|
||
|
(SUM(p.volume) * l.qty / u.factor) AS volume,
|
||
|
l.discount AS discount,
|
||
|
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 = self._select_additional_fields()
|
||
|
additional_fields_info = self._fill_pos_fields(additional_fields)
|
||
|
template = """,
|
||
|
%s AS %s"""
|
||
|
for fname, value in additional_fields_info.items():
|
||
|
select_ += template % (value, fname)
|
||
|
return select_
|
||
|
|
||
|
def _fill_pos_fields(self, additional_fields):
|
||
|
"""Hook to fill additional fields for the pos_sale.
|
||
|
|
||
|
:param values: dictionary of values to fill
|
||
|
:type values: dict
|
||
|
"""
|
||
|
return {x: 'NULL' for x in additional_fields}
|
||
|
|
||
|
def _from_pos(self):
|
||
|
return """
|
||
|
pos_order_line l
|
||
|
JOIN pos_order pos ON l.order_id = pos.id
|
||
|
LEFT JOIN res_partner partner ON (pos.partner_id=partner.id OR pos.partner_id = NULL)
|
||
|
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=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
|
||
|
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 """
|
||
|
l.sale_order_line_id IS NULL"""
|
||
|
|
||
|
def _group_by_pos(self):
|
||
|
return """
|
||
|
l.order_id,
|
||
|
l.product_id,
|
||
|
l.price_unit,
|
||
|
l.discount,
|
||
|
l.qty,
|
||
|
t.uom_id,
|
||
|
t.categ_id,
|
||
|
pos.name,
|
||
|
pos.date_order,
|
||
|
pos.partner_id,
|
||
|
pos.user_id,
|
||
|
pos.state,
|
||
|
pos.company_id,
|
||
|
pos.pricelist_id,
|
||
|
p.product_tmpl_id,
|
||
|
partner.country_id,
|
||
|
partner.industry_id,
|
||
|
partner.commercial_partner_id,
|
||
|
u.factor,
|
||
|
pos.crm_team_id,
|
||
|
currency_table.rate"""
|
||
|
|
||
|
def _query(self):
|
||
|
res = super()._query()
|
||
|
return res + f"""UNION ALL (
|
||
|
SELECT {self._select_pos()}
|
||
|
FROM {self._from_pos()}
|
||
|
WHERE {self._where_pos()}
|
||
|
GROUP BY {self._group_by_pos()}
|
||
|
)
|
||
|
"""
|