From bf9cbcc8d8c529b01ec158d682b7de4860e838e8 Mon Sep 17 00:00:00 2001 From: Akash Bhavsar Date: Thu, 15 Dec 2016 19:00:02 +0530 Subject: [PATCH] [IMP] pos_sale: Add analysis report about total sales from pos, eCommerce and sale Purpose ======= Create one report where we can see all sales (sales from sales, eCommerce, POS) grouped by channels Specification ============= New Report Sales > Reports , the name should be "All Channels Sales Orders" This report contains the following fields : name date product_id partner_id company_id user_id price_total pricelist_id categ_id = product_categ_id invoiced = amount to invoice analytic_account_id team_name country_id We thought about doing a kind of sale_order_common report, but we cannot re-use sale.report because of some field (qty_delivered, ...) that we cannot compute on pos orders. --- addons/pos_sale/__init__.py | 1 + addons/pos_sale/report/__init__.py | 4 + .../report/report_all_channels_sales.py | 44 +++++++++ addons/sale/__manifest__.py | 1 + addons/sale/report/__init__.py | 1 + .../sale/report/report_all_channels_sales.py | 92 +++++++++++++++++++ .../report_all_channels_sales_views.xml | 38 ++++++++ addons/sale/security/ir.model.access.csv | 2 + addons/website_sale/__init__.py | 3 + 9 files changed, 186 insertions(+) create mode 100644 addons/pos_sale/report/__init__.py create mode 100644 addons/pos_sale/report/report_all_channels_sales.py create mode 100644 addons/sale/report/report_all_channels_sales.py create mode 100644 addons/sale/report/report_all_channels_sales_views.xml diff --git a/addons/pos_sale/__init__.py b/addons/pos_sale/__init__.py index dc5e6b693d1..0bedb4deb09 100644 --- a/addons/pos_sale/__init__.py +++ b/addons/pos_sale/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import report \ No newline at end of file diff --git a/addons/pos_sale/report/__init__.py b/addons/pos_sale/report/__init__.py new file mode 100644 index 00000000000..72bdd30312f --- /dev/null +++ b/addons/pos_sale/report/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import report_all_channels_sales diff --git a/addons/pos_sale/report/report_all_channels_sales.py b/addons/pos_sale/report/report_all_channels_sales.py new file mode 100644 index 00000000000..1baf9caab89 --- /dev/null +++ b/addons/pos_sale/report/report_all_channels_sales.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class PosSaleReport(models.Model): + _inherit = "report.all.channels.sales" + + def _pos(self): + pos_str = """ + SELECT + (-1) * pol.id AS id, + pos.name AS name, + pos.partner_id AS partner_id, + pol.product_id AS product_id, + pro.product_tmpl_id AS product_tmpl_id, + pos.date_order AS date_order, + pos.user_id AS user_id, + pt.categ_id AS categ_id, + pos.company_id AS company_id, + ((pol.qty * pol.price_unit) * (100 - pol.discount) / 100) AS price_total, + pos.pricelist_id AS pricelist_id, + rp.country_id AS country_id, + (pol.qty * pol.price_unit) AS price_subtotal, + (pol.qty * u.factor) AS product_qty, + NULL AS analytic_account_id, + config.crm_team_id AS team_id + + FROM pos_order_line AS pol + JOIN pos_order pos ON (pos.id = pol.order_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 product_product pro ON (pol.product_id = pro.id) + LEFT JOIN product_template pt ON (pro.product_tmpl_id = pt.id) + LEFT JOIN product_category AS pc ON (pt.categ_id = pc.id) + LEFT JOIN res_company AS rc ON (pos.company_id = rc.id) + LEFT JOIN res_partner rp ON (rc.partner_id = rp.id) + LEFT JOIN product_uom u ON (u.id=pt.uom_id) + """ + return pos_str + + def _from(self): + return """(%s UNION ALL %s)""" % (self._so(), self._pos()) diff --git a/addons/sale/__manifest__.py b/addons/sale/__manifest__.py index cd6d3322e80..14574566fc8 100644 --- a/addons/sale/__manifest__.py +++ b/addons/sale/__manifest__.py @@ -18,6 +18,7 @@ This module contains all the common features of Sales Management and eCommerce. 'report/sale_report_views.xml', 'report/sale_report_templates.xml', 'report/invoice_report_templates.xml', + 'report/report_all_channels_sales_views.xml', 'security/sale_security.xml', 'security/ir.model.access.csv', 'wizard/sale_make_invoice_advance_views.xml', diff --git a/addons/sale/report/__init__.py b/addons/sale/report/__init__.py index 881c37f9e16..90248f477ca 100644 --- a/addons/sale/report/__init__.py +++ b/addons/sale/report/__init__.py @@ -3,3 +3,4 @@ from . import sale_report from . import invoice_report +from . import report_all_channels_sales diff --git a/addons/sale/report/report_all_channels_sales.py b/addons/sale/report/report_all_channels_sales.py new file mode 100644 index 00000000000..ed0219e2e0d --- /dev/null +++ b/addons/sale/report/report_all_channels_sales.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models, tools + + +class PosSaleReport(models.Model): + _name = "report.all.channels.sales" + _description = "All sales orders grouped by sales channels" + _auto = False + + name = fields.Char('Order Reference', readonly=True) + partner_id = fields.Many2one('res.partner', 'Partner', readonly=True) + product_id = fields.Many2one('product.product', string='Product', readonly=True) + product_tmpl_id = fields.Many2one('product.template', 'Product Template', readonly=True) + date_order = fields.Datetime(string='Date Order', readonly=True) + user_id = fields.Many2one('res.users', 'Salesperson', readonly=True) + categ_id = fields.Many2one('product.category', 'Product Category', readonly=True) + company_id = fields.Many2one('res.company', 'Company', readonly=True) + price_total = fields.Float('Total', readonly=True) + pricelist_id = fields.Many2one('product.pricelist', 'Pricelist', readonly=True) + country_id = fields.Many2one('res.country', 'Partner Country', readonly=True) + price_subtotal = fields.Float(string='Price Subtotal', readonly=True) + product_qty = fields.Float('Product Quantity', readonly=True) + analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True) + team_id = fields.Many2one('crm.team', 'Sales Channel', readonly=True) + + def _so(self): + so_str = """ + WITH currency_rate as (%s) + SELECT sol.id AS id, + so.name AS name, + so.partner_id AS partner_id, + sol.product_id AS product_id, + pro.product_tmpl_id AS product_tmpl_id, + so.date_order AS date_order, + so.user_id AS user_id, + pt.categ_id AS categ_id, + so.company_id AS company_id, + sol.price_total / COALESCE(cr.rate, 1.0) AS price_total, + so.pricelist_id AS pricelist_id, + rp.country_id AS country_id, + sol.price_subtotal / COALESCE (cr.rate, 1.0) AS price_subtotal, + (sol.product_uom_qty / u.factor * u2.factor) as product_qty, + so.project_id AS analytic_account_id, + so.team_id AS team_id + + FROM sale_order_line sol + JOIN sale_order so ON (sol.order_id = so.id) + LEFT JOIN product_product pro ON (sol.product_id = pro.id) + JOIN res_partner rp ON (so.partner_id = rp.id) + LEFT JOIN product_template pt ON (pro.product_tmpl_id = pt.id) + LEFT JOIN product_pricelist pp ON (so.pricelist_id = pp.id) + LEFT JOIN currency_rate cr ON (cr.currency_id = pp.currency_id AND + cr.company_id = so.company_id AND + cr.date_start <= COALESCE(so.date_order, now()) AND + (cr.date_end IS NULL OR cr.date_end > COALESCE(so.date_order, now()))) + LEFT JOIN product_uom u on (u.id=sol.product_uom) + LEFT JOIN product_uom u2 on (u2.id=pt.uom_id) + """ % self.env['res.currency']._select_companies_rates() + return so_str + + def _from(self): + return """(%s)""" % (self._so()) + + def get_main_request(self): + request = """ + CREATE or REPLACE VIEW %s AS + SELECT id AS id, + name, + partner_id, + product_id, + product_tmpl_id, + date_order, + user_id, + categ_id, + company_id, + price_total, + pricelist_id, + analytic_account_id, + country_id, + team_id, + price_subtotal, + product_qty + FROM %s + AS foo""" % (self._table, self._from()) + return request + + @api.model_cr + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + self.env.cr.execute(self.get_main_request()) diff --git a/addons/sale/report/report_all_channels_sales_views.xml b/addons/sale/report/report_all_channels_sales_views.xml new file mode 100644 index 00000000000..0a00b45a14e --- /dev/null +++ b/addons/sale/report/report_all_channels_sales_views.xml @@ -0,0 +1,38 @@ + + + + report.all.channels.sales.pivot + report.all.channels.sales + + + + + + + + + + report.all.channels.sales.search + report.all.channels.sales + + + + + + + + + + + + + All Channels Sales Orders + report.all.channels.sales + pivot + + + {'search_default_team_id': 1, 'search_default_current_year': 1} + + + + diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv index c32389e02d1..8795e4f2a04 100644 --- a/addons/sale/security/ir.model.access.csv +++ b/addons/sale/security/ir.model.access.csv @@ -51,3 +51,5 @@ access_account_journal_sale_manager,account.journal sale manager,account.model_a access_account_invoice_tax_sale_manager,account.invoice.tax sale manager,account.model_account_invoice_tax,sales_team.group_sale_salesman,1,0,0,0 access_account_tax_group_sale_manager,account.tax.group sale manager,account.model_account_tax_group,sales_team.group_sale_salesman,1,0,0,0 access_account_account_sale_manager,account.account sale manager,account.model_account_account,sales_team.group_sale_manager,1,0,0,0 +access_report_all_channels_sales_salesman,report.all.channels.sales,model_report_all_channels_sales,sales_team.group_sale_salesman,1,1,1,0 +access_report_all_channels_sales_manager,report.all.channels.sales,model_report_all_channels_sales,sales_team.group_sale_manager,1,1,1,1 diff --git a/addons/website_sale/__init__.py b/addons/website_sale/__init__.py index 91c5580fed3..7d34c7c054a 100644 --- a/addons/website_sale/__init__.py +++ b/addons/website_sale/__init__.py @@ -1,2 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + from . import controllers from . import models