From 17b8d7062c235b37601e6bb9afbcb44cb47222f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 15 Jun 2022 12:46:47 +0000 Subject: [PATCH] [PRF] mail: improve batch creation of activities Purpose of this commit is to improve batch creation of activities by trying to group checks by user and/or model when possible. Notably * subscribe partners in batch when several activities are assigned to the same user (use case: batch assign on leads, users may be assigned on several records in a single udpate); * check in batch access on partners; Task-2883589 (Activity performance and cleaning) Part-of: odoo/odoo#93682 --- addons/mail/models/mail_activity.py | 51 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index e9c86c05d08..d0488b30088 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -274,28 +274,41 @@ class MailActivity(models.Model): def create(self, vals_list): activities = super(MailActivity, self).create(vals_list) - for activity in activities: - need_sudo = False - try: # in multicompany, reading the partner might break - partner_id = activity.user_id.partner_id.id - except exceptions.AccessError: - need_sudo = True - partner_id = activity.user_id.sudo().partner_id.id + # find partners related to responsible users, separate readable from unreadable + if any(user != self.env.user for user in activities.user_id): + user_partners = activities.user_id.partner_id + readable_user_partners = user_partners._filter_access_rules_python('read') + else: + readable_user_partners = self.env.user.partner_id - # send a notification to assigned user; in case of manually done activity also check - # target has rights on document otherwise we prevent its creation. Automated activities - # are checked since they are integrated into business flows that should not crash. - if activity.user_id != self.env.user: - if not activity.automated: - activity._check_access_assignation() - if not self.env.context.get('mail_activity_quick_update', False): - if need_sudo: - activity.sudo().action_notify() - else: - activity.action_notify() + # when creating activities for other: send a notification to assigned user; + # in case of manually done activity also check target has rights on document + # otherwise we prevent its creation. Automated activities are checked since + # they are integrated into business flows that should not crash. + if self.env.context.get('mail_activity_quick_update'): + activities_to_notify = self.env['mail.activity'] + else: + activities_to_notify = activities.filtered(lambda act: act.user_id != self.env.user) + activities_to_notify.filtered(lambda act: not act.automated)._check_access_assignation() + if activities_to_notify: + to_sudo = activities_to_notify.filtered(lambda act: act.user_id.partner_id not in readable_user_partners) + other = activities_to_notify - to_sudo + to_sudo.sudo().action_notify() + other.action_notify() - self.env[activity.res_model].browse(activity.res_id).message_subscribe(partner_ids=[partner_id]) + # subscribe (batch by model and user to speedup) + for model, activity_data in activities._classify_by_model().items(): + per_user = dict() + for activity in activity_data['activities'].filtered(lambda act: act.user_id): + if activity.user_id not in per_user: + per_user[activity.user_id] = [activity.res_id] + else: + per_user[activity.user_id].append(activity.res_id) + for user, res_ids in per_user.items(): + pids = user.partner_id.ids if user.partner_id in readable_user_partners else user.sudo().partner_id.ids + self.env[model].browse(res_ids).message_subscribe(partner_ids=pids) + # send notifications about activity creation todo_activities = activities.filtered(lambda act: act.date_deadline <= fields.Date.today()) if todo_activities: self.env['bus.bus']._sendmany([