From 87970ea3448d9f402c3fa4b3c5d239a669569383 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 30 Aug 2017 14:02:39 +0200 Subject: [PATCH] [FIX] mail: add cached method to retrieve message subtypes This saves queries to retrieve message subtypes for a given model. --- addons/mail/models/mail_followers.py | 8 ++-- addons/mail/models/mail_message_subtype.py | 39 ++++++++++++++++++- addons/mail/models/mail_thread.py | 5 +-- .../tests/test_performance.py | 8 ++-- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py index 32d2e66b028..07ff6ea8c74 100644 --- a/addons/mail/models/mail_followers.py +++ b/addons/mail/models/mail_followers.py @@ -63,17 +63,15 @@ class Followers(models.Model): if follower.channel_id: c_exist.setdefault(follower.channel_id.id, list()).append(follower.res_id) - default_subtypes = self.env['mail.message.subtype'].search([ - ('default', '=', True), - '|', ('res_model', '=', res_model), ('res_model', '=', False)]) - external_default_subtypes = default_subtypes.filtered(lambda subtype: not subtype.internal) + default_subtypes, _internal_subtypes, external_subtypes = \ + self.env['mail.message.subtype'].default_subtypes(res_model) if force_mode: employee_pids = self.env['res.users'].sudo().search([('partner_id', 'in', list(partner_data)), ('share', '=', False)]).mapped('partner_id').ids for pid, data in partner_data.items(): if not data: if pid not in employee_pids: - partner_data[pid] = external_default_subtypes.ids + partner_data[pid] = external_subtypes.ids else: partner_data[pid] = default_subtypes.ids for cid, data in channel_data.items(): diff --git a/addons/mail/models/mail_message_subtype.py b/addons/mail/models/mail_message_subtype.py index dfe99860f75..df4a49374b5 100644 --- a/addons/mail/models/mail_message_subtype.py +++ b/addons/mail/models/mail_message_subtype.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import fields, models +from odoo import api, fields, models, tools class MailMessageSubtype(models.Model): @@ -40,3 +40,40 @@ class MailMessageSubtype(models.Model): default = fields.Boolean('Default', default=True, help="Activated by default when subscribing.") sequence = fields.Integer('Sequence', default=1, help="Used to order subtypes.") hidden = fields.Boolean('Hidden', help="Hide the subtype in the follower options") + + @api.model + def create(self, vals): + self.clear_caches() + return super(MailMessageSubtype, self).create(vals) + + def write(self, vals): + self.clear_caches() + return super(MailMessageSubtype, self).write(vals) + + def unlink(self): + self.clear_caches() + return super(MailMessageSubtype, self).unlink() + + def auto_subscribe_subtypes(self, model_name): + """ Retrieve the header subtypes and relations for the given model. """ + subtype_ids, relations = self._auto_subscribe_subtypes(model_name) + return self.browse(subtype_ids), relations + + @tools.ormcache('frozenset(self.env.user.groups_id.ids)', 'model_name') + def _auto_subscribe_subtypes(self, model_name): + domain = ['|', ('res_model', '=', False), ('parent_id.res_model', '=', model_name)] + subtypes = self.search(domain) + return subtypes.ids, set(subtype.relation_field for subtype in subtypes if subtype.relation_field) + + def default_subtypes(self, model_name): + """ Retrieve the default subtypes (all, internal, external) for the given model. """ + subtype_ids, internal_ids, external_ids = self._default_subtypes(model_name) + return self.browse(subtype_ids), self.browse(internal_ids), self.browse(external_ids) + + @tools.ormcache('frozenset(self.env.user.groups_id.ids)', 'model_name') + def _default_subtypes(self, model_name): + domain = [('default', '=', True), + '|', ('res_model', '=', model_name), ('res_model', '=', False)] + subtypes = self.search(domain) + internal = subtypes.filtered('internal') + return subtypes.ids, internal.ids, (subtypes - internal).ids diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 2587601e2b1..172b91aaf0d 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -2117,11 +2117,10 @@ class MailThread(models.AbstractModel): user_field_lst = self._message_get_auto_subscribe_fields(updated_fields) # fetch header subtypes - subtypes = self.env['mail.message.subtype'].search(['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)]) + subtypes, relation_fields = self.env['mail.message.subtype'].auto_subscribe_subtypes(self._name) # if no change in tracked field or no change in tracked relational field: quit - relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field is not False]) - if not any(relation in updated_fields for relation in relation_fields) and not user_field_lst: + if not any(relation in relation_fields for relation in updated_fields) and not user_field_lst: return True # find followers of headers, update structure for new followers diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py index 6c939b6177e..24bc466a4b1 100644 --- a/odoo/addons/test_performance/tests/test_performance.py +++ b/odoo/addons/test_performance/tests/test_performance.py @@ -123,7 +123,7 @@ class TestPerformance(TransactionCase): records.write({'value': self.int(20)}) - @queryCount(admin=7, demo=7) + @queryCount(admin=6, demo=6) def test_write_mail(self): """ Write records inheriting from 'mail.thread' (no recomputation). """ records = self.env['test_performance.mail'].search([]) @@ -132,7 +132,7 @@ class TestPerformance(TransactionCase): records.write({'name': self.str('X')}) - @queryCount(admin=9, demo=9) + @queryCount(admin=8, demo=8) def test_write_mail_with_recomputation(self): """ Write records inheriting from 'mail.thread' (with recomputation). """ records = self.env['test_performance.mail'].search([]) @@ -141,7 +141,7 @@ class TestPerformance(TransactionCase): records.write({'value': self.int(20)}) - @queryCount(admin=45, demo=62) + @queryCount(admin=44, demo=61) def test_write_mail_with_tracking(self): """ Write records inheriting from 'mail.thread' (with field tracking). """ record = self.env['test_performance.mail'].search([], limit=1) @@ -171,7 +171,7 @@ class TestPerformance(TransactionCase): model = self.env['test_performance.mail'] model.with_context(tracking_disable=True).create({'name': self.str('X')}) - @queryCount(admin=87, demo=114) + @queryCount(admin=85, demo=111) def test_create_mail_with_tracking(self): """ Create records inheriting from 'mail.thread' (with field tracking). """ model = self.env['test_performance.mail']