From bcc1efac485e00e01c93026c3d00704fb2f513cf Mon Sep 17 00:00:00 2001 From: Denis Vermylen Date: Tue, 7 Feb 2017 10:39:06 +0100 Subject: [PATCH] [IMP] sale*: improve dashboard computation time This commit improves crm.team compute methods and adds auto_join on: payment.transaction: field sale_order_id sale.order: field order_line Also move the dashboard_graph_type field in invisible in the kanban view to avoid triggering the computation of the graph when it's not needed. DO NOT FORWARD-PORT: a different patch will be made for the master branch --- addons/crm/models/crm_team.py | 10 ++--- addons/sale/models/sale.py | 2 +- addons/sale/models/sales_team.py | 44 ++++++++++--------- .../sales_team/views/sales_team_dashboard.xml | 2 +- addons/website_portal_sale/models/crm_team.py | 32 +++++--------- addons/website_portal_sale/models/payment.py | 2 +- addons/website_sale/models/crm_team.py | 32 +++++++------- 7 files changed, 60 insertions(+), 64 deletions(-) diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py index 0b1b08e892b..413f6230eb2 100644 --- a/addons/crm/models/crm_team.py +++ b/addons/crm/models/crm_team.py @@ -33,18 +33,18 @@ class Team(models.Model): ('type', '=', 'lead'), ('user_id', '=', False), ], ['team_id'], ['team_id']) - counts = dict((data['team_id'][0], data['team_id_count']) for data in leads_data) + counts = {datum['team_id'][0]: datum['team_id_count'] for datum in leads_data} for team in self: team.unassigned_leads_count = counts.get(team.id, 0) def _compute_opportunities(self): - opportunity_data = self.env['crm.opportunity.report'].read_group([ + opportunity_data = self.env['crm.lead'].read_group([ ('team_id', 'in', self.ids), ('probability', '<', 100), ('type', '=', 'opportunity'), - ], ['expected_revenue', 'team_id'], ['team_id']) - counts = dict((data['team_id'][0], data['team_id_count']) for data in opportunity_data) - amounts = dict((data['team_id'][0], data['expected_revenue']) for data in opportunity_data) + ], ['planned_revenue', 'probability', 'team_id'], ['team_id']) + counts = {datum['team_id'][0]: datum['team_id_count'] for datum in opportunity_data} + amounts = {datum['team_id'][0]: (datum['planned_revenue'] * datum['probability'] / 100) for datum in opportunity_data} for team in self: team.opportunities_count = counts.get(team.id, 0) team.opportunities_amount = amounts.get(team.id, 0) diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index a9d5c3dac20..0515bba6290 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -125,7 +125,7 @@ class SaleOrder(models.Model): project_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order.", copy=False) related_project_id = fields.Many2one('account.analytic.account', inverse='_inverse_project_id', related='project_id', string='Analytic Account', help="The analytic account related to a sales order.") - order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True) + order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True, auto_join=True) invoice_count = fields.Integer(string='# of Invoices', compute='_get_invoiced', readonly=True) invoice_ids = fields.Many2many("account.invoice", string='Invoices', compute="_get_invoiced", readonly=True, copy=False) diff --git a/addons/sale/models/sales_team.py b/addons/sale/models/sales_team.py index a318b32ecdd..2b11c7ab35b 100644 --- a/addons/sale/models/sales_team.py +++ b/addons/sale/models/sales_team.py @@ -37,34 +37,36 @@ class CrmTeam(models.Model): ]) def _compute_quotations_to_invoice(self): - amounts = self.env['sale.report'].read_group([ - ('team_id', 'in', self.filtered(lambda team: team.team_type != 'website').ids), - ('state', 'in', ['draft', 'sent']), - ], ['price_total', 'team_id', 'name'], ['team_id', 'name'], lazy=False) - for rec in amounts: - self.browse(rec['team_id'][0]).quotations_amount += rec['price_total'] - self.browse(rec['team_id'][0]).quotations_count += 1 + non_website_teams = self.filtered(lambda team: team.team_type != 'website') + if non_website_teams: + quotation_data = self.env['sale.report'].read_group([ + ('team_id', 'in', non_website_teams.ids), + ('state', 'in', ['draft', 'sent']), + ], ['price_total', 'team_id', 'name'], ['team_id', 'name'], lazy=False) + for datum in quotation_data: + self.browse(datum['team_id'][0]).quotations_amount += datum['price_total'] + self.browse(datum['team_id'][0]).quotations_count += 1 @api.multi def _compute_sales_to_invoice(self): - amounts = self.env['sale.report'].read_group([ + sale_order_data = self.env['sale.order'].read_group([ ('team_id', 'in', self.ids), - ('qty_to_invoice', '>', 0), - ], ['team_id', 'name'], ['team_id', 'name'], lazy=False) - for rec in amounts: - self.browse(rec['team_id'][0]).sales_to_invoice_count += 1 + ('order_line.qty_to_invoice', '>', 0), + ], ['team_id'], ['team_id']) + for datum in sale_order_data: + self.browse(datum['team_id'][0]).invoiced = datum['team_id_count'] @api.multi def _compute_invoiced(self): - for team in self: - invoices = self.env['account.invoice'].search([ - ('state', 'in', ['open', 'paid']), - ('team_id', '=', team.id), - ('date', '<=', date.today()), - ('date', '>=', date.today().replace(day=1)), - ('type', 'in', ['out_invoice', 'out_refund']), - ]) - team.invoiced = sum(invoices.mapped('amount_untaxed_signed')) + invoice_data = self.env['account.invoice'].read_group([ + ('state', 'in', ['open', 'paid']), + ('team_id', 'in', self.ids), + ('date', '<=', date.today()), + ('date', '>=', date.today().replace(day=1)), + ('type', 'in', ['out_invoice', 'out_refund']), + ], ['amount_untaxed_signed', 'team_id'], ['team_id']) + for datum in invoice_data: + self.browse(datum['team_id'][0]).invoiced = datum['amount_untaxed_signed'] def _graph_date_column(self): if self.dashboard_graph_model in ['sales', 'invoices']: diff --git a/addons/sales_team/views/sales_team_dashboard.xml b/addons/sales_team/views/sales_team_dashboard.xml index dd4a69fb99b..3efb404e549 100644 --- a/addons/sales_team/views/sales_team_dashboard.xml +++ b/addons/sales_team/views/sales_team_dashboard.xml @@ -9,7 +9,6 @@ - @@ -70,6 +69,7 @@
+
diff --git a/addons/website_portal_sale/models/crm_team.py b/addons/website_portal_sale/models/crm_team.py index 827c7297cb2..411fa6a21ab 100644 --- a/addons/website_portal_sale/models/crm_team.py +++ b/addons/website_portal_sale/models/crm_team.py @@ -22,23 +22,15 @@ class CrmTeam(models.Model): def _compute_payment_transactions(self): for team in self: - query = """ - SELECT amount, - currency_id, - state - FROM payment_transaction - WHERE sale_order_id in %s - AND state in ('authorized', 'pending') - """ - sale_order_ids = self.env['sale.order'].search([('team_id', '=', team.id)]).ids - if sale_order_ids: - self._cr.execute(query, [tuple(sale_order_ids)]) - transactions = self._cr.dictfetchall() - for line in transactions: - line_currency = self.env['res.currency'].browse(line['currency_id']) - if line['state'] == 'authorized': - team.authorized_payment_transactions_count += 1 - team.authorized_payment_transactions_amount += line_currency.compute(line['amount'], self.env.user.company_id.currency_id) - elif line['state'] == 'pending': - team.pending_payment_transactions_count += 1 - team.pending_payment_transactions_amount += line_currency.compute(line['amount'], self.env.user.company_id.currency_id) + payment_data = self.env['payment.transaction'].read_group([ + ('state', 'in', ['authorized', 'pending']), + ('sale_order_id.team_id', '=', team.id) + ], ['amount', 'currency_id', 'state'], ['state', 'currency_id'], lazy=False) + for datum in payment_data: + datum_currency = self.env['res.currency'].browse(datum['currency_id'][0]) + if datum['state'] == 'authorized': + team.authorized_payment_transactions_count += datum['__count'] + team.authorized_payment_transactions_amount += datum_currency.compute(datum['amount'], self.env.user.company_id.currency_id) + elif datum['state'] == 'pending': + team.pending_payment_transactions_count += datum['__count'] + team.pending_payment_transactions_amount += datum_currency.compute(datum['amount'], self.env.user.company_id.currency_id) diff --git a/addons/website_portal_sale/models/payment.py b/addons/website_portal_sale/models/payment.py index d94b429bf18..9842567abb1 100644 --- a/addons/website_portal_sale/models/payment.py +++ b/addons/website_portal_sale/models/payment.py @@ -11,7 +11,7 @@ class PaymentTransaction(models.Model): _inherit = 'payment.transaction' # link with the sales order - sale_order_id = fields.Many2one('sale.order', string='Sales Order') + sale_order_id = fields.Many2one('sale.order', string='Sales Order', auto_join=True) def _generate_and_pay_invoice(self, tx, acquirer_name): tx.sale_order_id._force_lines_to_invoice_policy_order() diff --git a/addons/website_sale/models/crm_team.py b/addons/website_sale/models/crm_team.py index f512191d77b..ef9cf229068 100644 --- a/addons/website_sale/models/crm_team.py +++ b/addons/website_sale/models/crm_team.py @@ -13,26 +13,28 @@ class CrmTeam(models.Model): website_ids = fields.One2many('website', 'salesteam_id', string='Websites', help="Websites using this sales channel") abandoned_carts_count = fields.Integer( compute='_compute_abandoned_carts', - string='Number of transactions to capture', readonly=True) + string='Number of Abandoned Carts', readonly=True) abandoned_carts_amount = fields.Integer( compute='_compute_abandoned_carts', - string='Amount of transactions to capture', readonly=True) + string='Amount of Abandoned Carts', readonly=True) def _compute_abandoned_carts(self): + # abandoned carts are draft sales orders that have no order lines, + # a partner other than the public user, and created over an hour ago website_teams = self.filtered(lambda team: team.team_type == 'website') - # abandoned carts are draft sales orders that have no order lines, a partner other than the public user, and created over an hour ago - abandoned_carts_data = self.env['sale.order'].read_group([ - ('team_id', 'in', website_teams.ids), - ('date_order', '<', fields.Datetime.to_string(datetime.now() - relativedelta(hours=1))), - ('state', '=', 'draft'), - ('partner_id', '!=', self.env.ref('base.public_partner').id), - ('order_line', '!=', False), - ], ['amount_total', 'team_id'], ['team_id']) - counts = dict((data['team_id'][0], data['team_id_count']) for data in abandoned_carts_data) - amounts = dict((data['team_id'][0], data['amount_total']) for data in abandoned_carts_data) - for team in website_teams: - team.abandoned_carts_count = counts.get(team.id, 0) - team.abandoned_carts_amount = amounts.get(team.id, 0) + if website_teams: + abandoned_carts_data = self.env['sale.order'].read_group([ + ('team_id', 'in', website_teams.ids), + ('date_order', '<', fields.Datetime.to_string(datetime.now() - relativedelta(hours=1))), + ('state', '=', 'draft'), + ('partner_id', '!=', self.env.ref('base.public_partner').id), + ('order_line', '!=', False), + ], ['amount_total', 'team_id'], ['team_id']) + counts = {data['team_id'][0]: data['team_id_count'] for data in abandoned_carts_data} + amounts = {data['team_id'][0]: data['amount_total'] for data in abandoned_carts_data} + for team in website_teams: + team.abandoned_carts_count = counts.get(team.id, 0) + team.abandoned_carts_amount = amounts.get(team.id, 0) def _compute_dashboard_button_name(self): website_teams = self.filtered(lambda team: team.team_type == 'website' and not team.use_quotations)