[FIX] mail: apply multi-company when feching systray activities
A raw query is not necessary to produce the desired result, found activities need to be kept only if the corresponding record can be found with standard search (which includes multi-company check). Part of task-3266643 closes odoo/odoo#123070 X-original-commit: 9dd7ae942aebe2cfd3e2dcd52e10b3bff5c8e0a9 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, exceptions, fields, models, modules, tools
|
||||
from collections import defaultdict
|
||||
|
||||
from odoo import _, api, fields, models, modules, tools
|
||||
from odoo.tools import email_normalize
|
||||
|
||||
|
||||
@@ -277,44 +278,43 @@ class Users(models.Model):
|
||||
|
||||
@api.model
|
||||
def systray_get_activities(self):
|
||||
query = """SELECT m.id, count(*), act.res_model as model,
|
||||
CASE
|
||||
WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today'
|
||||
WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue'
|
||||
WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned'
|
||||
END AS states
|
||||
FROM mail_activity AS act
|
||||
JOIN ir_model AS m ON act.res_model_id = m.id
|
||||
WHERE user_id = %(user_id)s
|
||||
GROUP BY m.id, states, act.res_model;
|
||||
"""
|
||||
self.env.cr.execute(query, {
|
||||
'today': fields.Date.context_today(self),
|
||||
'user_id': self.env.uid,
|
||||
})
|
||||
activity_data = self.env.cr.dictfetchall()
|
||||
model_ids = [a['id'] for a in activity_data]
|
||||
model_names = {n[0]: n[1] for n in self.env['ir.model'].sudo().browse(model_ids).name_get()}
|
||||
|
||||
activities = self.env["mail.activity"].search([("user_id", "=", self.env.uid)])
|
||||
activities_by_record_by_model_name = defaultdict(lambda: defaultdict(lambda: self.env["mail.activity"]))
|
||||
for activity in activities:
|
||||
record = self.env[activity.res_model].browse(activity.res_id)
|
||||
activities_by_record_by_model_name[activity.res_model][record] += activity
|
||||
model_ids = list({self.env["ir.model"]._get(name).id for name in activities_by_record_by_model_name.keys()})
|
||||
user_activities = {}
|
||||
for activity in activity_data:
|
||||
if not user_activities.get(activity['model']):
|
||||
module = self.env[activity['model']]._original_module
|
||||
icon = module and modules.module.get_module_icon(module)
|
||||
user_activities[activity['model']] = {
|
||||
'id': activity['id'],
|
||||
'name': model_names[activity['id']],
|
||||
'model': activity['model'],
|
||||
'type': 'activity',
|
||||
'icon': icon,
|
||||
'total_count': 0, 'today_count': 0, 'overdue_count': 0, 'planned_count': 0,
|
||||
}
|
||||
user_activities[activity['model']]['%s_count' % activity['states']] += activity['count']
|
||||
if activity['states'] in ('today', 'overdue'):
|
||||
user_activities[activity['model']]['total_count'] += activity['count']
|
||||
|
||||
user_activities[activity['model']]['actions'] = [{
|
||||
'icon': 'fa-clock-o',
|
||||
'name': 'Summary',
|
||||
}]
|
||||
for model_name, activities_by_record in activities_by_record_by_model_name.items():
|
||||
domain = [("id", "in", list({r.id for r in activities_by_record.keys()}))]
|
||||
allowed_records = self.env[model_name].search(domain)
|
||||
if not allowed_records:
|
||||
continue
|
||||
module = self.env[model_name]._original_module
|
||||
icon = module and modules.module.get_module_icon(module)
|
||||
model = self.env["ir.model"]._get(model_name).with_prefetch(model_ids)
|
||||
user_activities[model_name] = {
|
||||
"id": model.id,
|
||||
"name": model.name,
|
||||
"model": model_name,
|
||||
"type": "activity",
|
||||
"icon": icon,
|
||||
"total_count": 0,
|
||||
"today_count": 0,
|
||||
"overdue_count": 0,
|
||||
"planned_count": 0,
|
||||
"actions": [
|
||||
{
|
||||
"icon": "fa-clock-o",
|
||||
"name": "Summary",
|
||||
}
|
||||
],
|
||||
}
|
||||
for record, activities in activities_by_record.items():
|
||||
if record not in allowed_records:
|
||||
continue
|
||||
for activity in activities:
|
||||
user_activities[model_name]["%s_count" % activity.state] += 1
|
||||
if activity.state in ("today", "overdue"):
|
||||
user_activities[model_name]["total_count"] += 1
|
||||
return list(user_activities.values())
|
||||
|
||||
@@ -112,6 +112,15 @@ class MailTestTrackMonetary(models.Model):
|
||||
company_currency = fields.Many2one("res.currency", string='Currency', related='company_id.currency_id', readonly=True, tracking=True)
|
||||
revenue = fields.Monetary('Revenue', currency_field='company_currency', tracking=True)
|
||||
|
||||
class MailTestMultiCompanyWithActivity(models.Model):
|
||||
""" This model can be used in multi company tests with activity"""
|
||||
_name = "mail.test.multi.company.with.activity"
|
||||
_description = "Test Multi Company Mail With Activity"
|
||||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||
|
||||
name = fields.Char()
|
||||
company_id = fields.Many2one("res.company")
|
||||
|
||||
|
||||
class MailTestSelectionTracking(models.Model):
|
||||
""" Test tracking for selection fields """
|
||||
|
||||
@@ -39,6 +39,8 @@ access_mail_test_multi_company_user,mail.test.multi.company.user,model_mail_test
|
||||
access_mail_test_multi_company_portal,mail.test.multi.company.portal,model_mail_test_multi_company,base.group_portal,1,0,0,0
|
||||
access_mail_test_multi_company_read_user,mail.test.multi.company.read.user,model_mail_test_multi_company_read,base.group_user,1,1,1,1
|
||||
access_mail_test_multi_company_read_portal,mail.test.multi.company.read.portal,model_mail_test_multi_company_read,base.group_portal,1,0,0,0
|
||||
access_mail_test_multi_company_with_activity_user,mail.test.multi.company.with.activity.user,model_mail_test_multi_company_with_activity,base.group_user,1,1,1,1
|
||||
access_mail_test_multi_company_with_activity_portal,mail.test.multi.company.with.activity.portal,model_mail_test_multi_company_with_activity,base.group_portal,1,0,0,0
|
||||
access_mail_test_nothread_user,mail.test.nothread.user,model_mail_test_nothread,base.group_user,1,1,1,1
|
||||
access_mail_test_nothread_portal,mail.test.nothread.portal,model_mail_test_nothread,base.group_portal,1,0,0,0
|
||||
access_mail_test_track_all,mail.test.track.all,model_mail_test_track_all,base.group_user,1,1,1,1
|
||||
|
||||
|
@@ -16,6 +16,13 @@
|
||||
<field name="global" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_test_multi_company_with_activity_rule" model="ir.rule">
|
||||
<field name="name">Mail Test Multi Company With Activity</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_multi_company_with_activity"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<!-- TICKET-LIKE -->
|
||||
<record id="mail_test_ticket_rule_portal" model="ir.rule">
|
||||
<field name="name">Portal Mail Test Ticket</field>
|
||||
|
||||
@@ -383,6 +383,50 @@ class TestMultiCompanySetup(MailCommon, TestRecipients):
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
def test_systray_get_activities(self):
|
||||
self.env["mail.activity"].search([]).unlink()
|
||||
user_admin = self.user_admin.with_user(self.user_admin)
|
||||
test_records = self.env["mail.test.multi.company.with.activity"].create(
|
||||
[
|
||||
{"name": "Test1", "company_id": user_admin.company_id.id},
|
||||
{"name": "Test2", "company_id": self.company_2.id},
|
||||
]
|
||||
)
|
||||
test_records[0].activity_schedule("test_mail.mail_act_test_todo", user_id=user_admin.id)
|
||||
test_records[1].activity_schedule("test_mail.mail_act_test_todo", user_id=user_admin.id)
|
||||
res_all = user_admin.systray_get_activities()
|
||||
self.assertEqual(
|
||||
res_all[0],
|
||||
{
|
||||
"actions": [{"icon": "fa-clock-o", "name": "Summary"}],
|
||||
"icon": "/base/static/description/icon.png",
|
||||
"id": self.env["ir.model"]._get_id("mail.test.multi.company.with.activity"),
|
||||
"model": "mail.test.multi.company.with.activity",
|
||||
"name": "Test Multi Company Mail With Activity",
|
||||
"overdue_count": 0,
|
||||
"planned_count": 0,
|
||||
"today_count": 2,
|
||||
"total_count": 2,
|
||||
"type": "activity",
|
||||
}
|
||||
)
|
||||
res_c2 = user_admin.with_context(allowed_company_ids=[self.company_2.id]).systray_get_activities()
|
||||
self.assertEqual(
|
||||
res_c2[0],
|
||||
{
|
||||
"actions": [{"icon": "fa-clock-o", "name": "Summary"}],
|
||||
"icon": "/base/static/description/icon.png",
|
||||
"id": self.env["ir.model"]._get_id("mail.test.multi.company.with.activity"),
|
||||
"model": "mail.test.multi.company.with.activity",
|
||||
"name": "Test Multi Company Mail With Activity",
|
||||
"overdue_count": 0,
|
||||
"planned_count": 0,
|
||||
"today_count": 1,
|
||||
"total_count": 1,
|
||||
"type": "activity",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install', 'multi_company')
|
||||
class TestMultiCompanyRedirect(MailCommon, HttpCase):
|
||||
|
||||
Reference in New Issue
Block a user