diff --git a/addons/crm/models/calendar.py b/addons/crm/models/calendar.py
index 99d69dbf76c..0c55f665e4e 100644
--- a/addons/crm/models/calendar.py
+++ b/addons/crm/models/calendar.py
@@ -7,17 +7,6 @@ from odoo import api, fields, models
class CalendarEvent(models.Model):
_inherit = 'calendar.event'
- def _is_crm_lead(self, defaults, ctx=None):
- """
- This method checks if the concerned model is a CRM lead.
- The information is not always in the defaults values,
- this is why it is necessary to check the context too.
- """
- res_model = defaults.get('res_model', False) or ctx and ctx.get('default_res_model')
- res_model_id = defaults.get('res_model_id', False) or ctx and ctx.get('default_res_model_id')
-
- return res_model and res_model == 'crm.lead' or res_model_id and self.env['ir.model'].sudo().browse(res_model_id).model == 'crm.lead'
-
@api.model
def default_get(self, fields):
if self.env.context.get('default_opportunity_id'):
@@ -28,13 +17,16 @@ class CalendarEvent(models.Model):
defaults = super(CalendarEvent, self).default_get(fields)
# sync res_model / res_id to opportunity id (aka creating meeting from lead chatter)
- ctx = self.env.context
if 'opportunity_id' not in defaults:
- if self._is_crm_lead(defaults, ctx):
- defaults['opportunity_id'] = defaults.get('res_id', False) or ctx.get('default_res_id', False)
+ if self._is_crm_lead(defaults, self.env.context):
+ defaults['opportunity_id'] = defaults.get('res_id', False) or self.env.context.get('default_res_id', False)
return defaults
+ opportunity_id = fields.Many2one(
+ 'crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]",
+ index=True, ondelete='set null')
+
def _compute_is_highlighted(self):
super(CalendarEvent, self)._compute_is_highlighted()
if self.env.context.get('active_model') == 'crm.lead':
@@ -43,8 +35,6 @@ class CalendarEvent(models.Model):
if event.opportunity_id.id == opportunity_id:
event.is_highlighted = True
- opportunity_id = fields.Many2one('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]")
-
@api.model_create_multi
def create(self, vals):
events = super(CalendarEvent, self).create(vals)
@@ -52,3 +42,14 @@ class CalendarEvent(models.Model):
if event.opportunity_id and not event.activity_ids:
event.opportunity_id.log_meeting(event.name, event.start, event.duration)
return events
+
+ def _is_crm_lead(self, defaults, ctx=None):
+ """
+ This method checks if the concerned model is a CRM lead.
+ The information is not always in the defaults values,
+ this is why it is necessary to check the context too.
+ """
+ res_model = defaults.get('res_model', False) or ctx and ctx.get('default_res_model')
+ res_model_id = defaults.get('res_model_id', False) or ctx and ctx.get('default_res_model_id')
+
+ return res_model and res_model == 'crm.lead' or res_model_id and self.env['ir.model'].sudo().browse(res_model_id).model == 'crm.lead'
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py
index fb5c891e377..2a9a9d79b9d 100644
--- a/addons/crm/models/crm_lead.py
+++ b/addons/crm/models/crm_lead.py
@@ -293,8 +293,13 @@ class Lead(models.Model):
lead.expected_revenue = round((lead.planned_revenue or 0.0) * (lead.probability or 0) / 100.0, 2)
def _compute_meeting_count(self):
- meeting_data = self.env['calendar.event'].sudo().read_group([('opportunity_id', 'in', self.ids)], ['opportunity_id'], ['opportunity_id'])
- mapped_data = {m['opportunity_id'][0]: m['opportunity_id_count'] for m in meeting_data}
+ if self.ids:
+ meeting_data = self.env['calendar.event'].sudo().read_group([
+ ('opportunity_id', 'in', self.ids)
+ ], ['opportunity_id'], ['opportunity_id'])
+ mapped_data = {m['opportunity_id'][0]: m['opportunity_id_count'] for m in meeting_data}
+ else:
+ mapped_data = dict()
for lead in self:
lead.meeting_count = mapped_data.get(lead.id, 0)
diff --git a/addons/crm/models/res_partner.py b/addons/crm/models/res_partner.py
index 8129b6f9536..f214c7d5549 100644
--- a/addons/crm/models/res_partner.py
+++ b/addons/crm/models/res_partner.py
@@ -37,13 +37,42 @@ class Partner(models.Model):
return rec
def _compute_opportunity_count(self):
+ if self.ids:
+ lead_group_data = self.env['crm.lead'].read_group(
+ [('partner_id.commercial_partner_id', 'in', self.ids)],
+ ['partner_id'], ['partner_id']
+ )
+ else:
+ lead_group_data = []
+ partners = dict(
+ (m['partner_id'][0], m['partner_id_count'])
+ for m in lead_group_data)
+ commercial_partners = {}
+ for partner in self.browse(partners.keys()):
+ commercial_partners.setdefault(partner.commercial_partner_id.id, 0)
+ commercial_partners[partner.commercial_partner_id.id] += partners[partner.id]
for partner in self:
- operator = 'child_of' if partner.is_company else '=' # the opportunity count should counts the opportunities of this company and all its contacts
- partner.opportunity_count = self.env['crm.lead'].search_count([('partner_id', operator, partner.id), ('type', '=', 'opportunity')])
+ if partner.is_company:
+ partner.opportunity_count = commercial_partners.get(partner.id, 0)
+ else:
+ partner.opportunity_count = partners.get(partner.id, 0)
def _compute_meeting_count(self):
+ if self.ids:
+ self.env.cr.execute("""
+ SELECT res_partner_id, calendar_event_id, count(1)
+ FROM calendar_event_res_partner_rel
+ WHERE res_partner_id IN %s
+ GROUP BY res_partner_id, calendar_event_id
+ """, [tuple(self.ids)])
+ meeting_data = self.env.cr.fetchall()
+ events = [row[1] for row in meeting_data]
+ valid_events = self.env['calendar.event'].search([('id', 'in', events)]) # filter for ACLs
+ meetings = dict((m[0], m[2]) for m in meeting_data if m[1] in valid_events.ids)
+ else:
+ meetings = dict()
for partner in self:
- partner.meeting_count = len(partner.meeting_ids)
+ partner.meeting_count = meetings.get(partner.id, 0)
def schedule_meeting(self):
partner_ids = self.ids
diff --git a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
index b62e454ccbb..598fe68d8d6 100644
--- a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
+++ b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
@@ -42,7 +42,7 @@ class CRMLeadMiningRequest(models.Model):
user_id = fields.Many2one('res.users', string='Salesperson')
tag_ids = fields.Many2many('crm.tag', string='Tags')
lead_ids = fields.One2many('crm.lead', 'lead_mining_request_id', string='Generated Lead / Opportunity')
- leads_count = fields.Integer(compute='_compute_leads_count', string='Number of Generated Leads')
+ lead_count = fields.Integer(compute='_compute_lead_count', string='Number of Generated Leads')
# Company Criteria Filter
filter_on_size = fields.Boolean(string='Filter on Size', default=False)
@@ -74,10 +74,19 @@ class CRMLeadMiningRequest(models.Model):
record.lead_credits = _('%d credits will be consumed to find %d companies.') % (company_credits, record.lead_number)
record.lead_total_credits = _("This makes a total of %d credits for this request.") % (total_contact_credits + company_credits)
- @api.depends('lead_ids')
- def _compute_leads_count(self):
- for req in self:
- req.leads_count = len(req.lead_ids)
+ @api.depends('lead_ids.lead_mining_request_id')
+ def _compute_lead_count(self):
+ if self.ids:
+ leads_data = self.env['crm.lead'].read_group(
+ [('lead_mining_request_id', 'in', self.ids)],
+ ['lead_mining_request_id'], ['lead_mining_request_id'])
+ else:
+ leads_data = []
+ mapped_data = dict(
+ (m['lead_mining_request_id'][0], m['lead_mining_request_id_count'])
+ for m in leads_data)
+ for request in self:
+ request.lead_count = mapped_data.get(request.id, 0)
@api.onchange('lead_number')
def _onchange_lead_number(self):
diff --git a/addons/crm_iap_lead/views/crm_iap_lead_views.xml b/addons/crm_iap_lead/views/crm_iap_lead_views.xml
index 41bf1b858a6..f76fb55013c 100644
--- a/addons/crm_iap_lead/views/crm_iap_lead_views.xml
+++ b/addons/crm_iap_lead/views/crm_iap_lead_views.xml
@@ -19,14 +19,14 @@
diff --git a/addons/crm_iap_lead_website/models/crm_reveal_rule.py b/addons/crm_iap_lead_website/models/crm_reveal_rule.py
index 4da34077042..e34af7463af 100644
--- a/addons/crm_iap_lead_website/models/crm_reveal_rule.py
+++ b/addons/crm_iap_lead_website/models/crm_reveal_rule.py
@@ -57,7 +57,7 @@ class CRMRevealRule(models.Model):
user_id = fields.Many2one('res.users', string='Salesperson')
priority = fields.Selection(crm_stage.AVAILABLE_PRIORITIES, string='Priority')
lead_ids = fields.One2many('crm.lead', 'reveal_rule_id', string='Generated Lead / Opportunity')
- leads_count = fields.Integer(compute='_compute_leads_count', string='Number of Generated Leads')
+ lead_count = fields.Integer(compute='_compute_lead_count', string='Number of Generated Leads')
opportunity_count = fields.Integer(compute='_compute_leads_count', string='Number of Generated Opportunity')
# This limits the number of extra contact.
@@ -101,7 +101,7 @@ class CRMRevealRule(models.Model):
self.clear_caches() # Clear the cache in order to recompute _get_active_rules
return super(CRMRevealRule, self).unlink()
- def _compute_leads_count(self):
+ def _compute_lead_count(self):
leads = self.env['crm.lead'].read_group([
('reveal_rule_id', 'in', self.ids)
], fields=['reveal_rule_id', 'type'], groupby=['reveal_rule_id', 'type'], lazy=False)
diff --git a/addons/crm_iap_lead_website/views/crm_reveal_views.xml b/addons/crm_iap_lead_website/views/crm_reveal_views.xml
index 80d34fbbea9..cda1577498c 100644
--- a/addons/crm_iap_lead_website/views/crm_reveal_views.xml
+++ b/addons/crm_iap_lead_website/views/crm_reveal_views.xml
@@ -13,9 +13,9 @@
Opportunities
-