Merge PR #1222 into 15.0

Signed-off-by pedrobaeza
pull/1230/head
OCA-git-bot 2023-10-09 10:26:34 +00:00
commit dd49b6df24
3 changed files with 121 additions and 102 deletions

View File

@ -1,6 +1,9 @@
# Copyright 2018-22 ForgeFlow <http://www.forgeflow.com> # Copyright 2018-22 ForgeFlow <http://www.forgeflow.com>
# Copyright 2023 Tecnativa - Víctor Martínez
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models, modules from collections import defaultdict
from odoo import api, fields, models
class ResUsers(models.Model): class ResUsers(models.Model):
@ -8,51 +11,61 @@ class ResUsers(models.Model):
@api.model @api.model
def systray_get_activities(self): def systray_get_activities(self):
# Here we totally override the method. Not very nice, but # TODO: Simplify if Odoo allows to modify query
# we should perhaps ask Odoo to add a hook here. res = super().systray_get_activities()
query = """SELECT m.id, count(*), act.res_model as model, # Convert list to dict
CASE user_activities = {}
WHEN %(today)s::date - for item in res:
act.date_deadline::date = 0 Then 'today' user_activities[item["model"]] = item
WHEN %(today)s::date - # Redo the method only with the archived records and subtract them.
act.date_deadline::date > 0 Then 'overdue' query = """SELECT array_agg(res_id) as res_ids, m.id, count(*),
WHEN %(today)s::date - CASE
act.date_deadline::date < 0 Then 'planned' WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today'
END AS states WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue'
FROM mail_activity AS act WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned'
JOIN ir_model AS m ON act.res_model_id = m.id END AS states
WHERE user_id = %(user_id)s FROM mail_activity AS act
AND act.done = False JOIN ir_model AS m ON act.res_model_id = m.id
GROUP BY m.id, states, act.res_model; WHERE user_id = %(user_id)s
""" AND act.active = False
GROUP BY m.id, states;
"""
self.env.cr.execute( self.env.cr.execute(
query, {"today": fields.Date.context_today(self), "user_id": self.env.uid} query,
{
"today": fields.Date.context_today(self),
"user_id": self.env.uid,
},
) )
activity_data = self.env.cr.dictfetchall() activity_data = self.env.cr.dictfetchall()
model_ids = [a["id"] for a in activity_data] records_by_state_by_model = defaultdict(
model_names = { lambda: {"today": set(), "overdue": set(), "planned": set(), "all": set()}
n[0]: n[1] for n in self.env["ir.model"].sudo().browse(model_ids).name_get() )
} for data in activity_data:
records_by_state_by_model[data["id"]][data["states"]] = set(data["res_ids"])
user_activities = {} records_by_state_by_model[data["id"]]["all"] = records_by_state_by_model[
for activity in activity_data: data["id"]
if not user_activities.get(activity["model"]): ]["all"] | set(data["res_ids"])
user_activities[activity["model"]] = { for model_id in records_by_state_by_model:
"name": model_names[activity["id"]], model_dic = records_by_state_by_model[model_id]
"model": activity["model"], model = (
"icon": modules.module.get_module_icon( self.env["ir.model"]
self.env[activity["model"]]._original_module .sudo()
), .browse(model_id)
"total_count": 0, .with_prefetch(tuple(records_by_state_by_model.keys()))
"today_count": 0, )
"overdue_count": 0, allowed_records = self.env[model.model].search(
"planned_count": 0, [("id", "in", tuple(model_dic["all"]))]
"type": "activity", )
} if not allowed_records:
user_activities[activity["model"]][ continue
"%s_count" % activity["states"] today = len(model_dic["today"] & set(allowed_records.ids))
] += activity["count"] overdue = len(model_dic["overdue"] & set(allowed_records.ids))
if activity["states"] in ("today", "overdue"): # Decrease total
user_activities[activity["model"]]["total_count"] += activity["count"] user_activities[model.model]["total_count"] -= today + overdue
user_activities[model.model]["today_count"] -= today
user_activities[model.model]["overdue_count"] -= overdue
user_activities[model.model]["planned_count"] -= len(
model_dic["planned"] & set(allowed_records.ids)
)
return list(user_activities.values()) return list(user_activities.values())

View File

@ -1,31 +1,39 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# Copyright 2023 Tecnativa - Víctor Martínez
from datetime import date from datetime import date
from odoo.tests.common import TransactionCase from odoo.tests.common import TransactionCase, new_test_user
class TestMailActivityDoneMethods(TransactionCase): class TestMailActivityDoneMethods(TransactionCase):
def setUp(self): @classmethod
super(TestMailActivityDoneMethods, self).setUp() def setUpClass(cls):
super().setUpClass()
self.employee = self.env["res.users"].create( cls.env = cls.env(
{ context=dict(
"company_id": self.env.ref("base.main_company").id, cls.env.context,
"name": "Test User", mail_activity_quick_update=True,
"login": "testuser", mail_create_nolog=True,
"groups_id": [(6, 0, [self.env.ref("base.group_user").id])], mail_create_nosubscribe=True,
} mail_notrack=True,
no_reset_password=True,
tracking_disable=True,
)
) )
activity_type = self.env["mail.activity.type"].search( cls.employee = new_test_user(
cls.env,
name="Test User",
login="testuser",
)
activity_type = cls.env["mail.activity.type"].search(
[("name", "=", "Meeting")], limit=1 [("name", "=", "Meeting")], limit=1
) )
self.act1 = self.env["mail.activity"].create( cls.act1 = cls.env["mail.activity"].create(
{ {
"activity_type_id": activity_type.id, "activity_type_id": activity_type.id,
"res_id": self.env.ref("base.res_partner_1").id, "res_id": cls.env.ref("base.res_partner_1").id,
"res_model_id": self.env["ir.model"]._get("res.partner").id, "res_model_id": cls.env["ir.model"]._get("res.partner").id,
"user_id": self.employee.id, "user_id": cls.employee.id,
"date_deadline": date.today(), "date_deadline": date.today(),
} }
) )
@ -35,7 +43,12 @@ class TestMailActivityDoneMethods(TransactionCase):
self.assertEqual(self.act1.state, "done") self.assertEqual(self.act1.state, "done")
def test_systray_get_activities(self): def test_systray_get_activities(self):
act_count = self.employee.with_user(self.employee).systray_get_activities() res = self.employee.with_user(self.employee).systray_get_activities()
self.assertEqual( self.assertEqual(res[0]["total_count"], 1)
len(act_count), 1, "Number of activities should be equal to one" self.act1.action_feedback()
) self.assertFalse(self.act1.active)
self.assertEqual(self.act1.state, "done")
self.assertTrue(self.act1.done)
self.act1.flush()
res = self.employee.with_user(self.employee).systray_get_activities()
self.assertEqual(res[0]["total_count"], 0)

View File

@ -2,52 +2,45 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tests.common import Form, TransactionCase from odoo.tests.common import Form, TransactionCase, new_test_user
class TestMailActivityTeam(TransactionCase): class TestMailActivityTeam(TransactionCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super().setUpClass() super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls.env = cls.env(
context=dict(
cls.env.context,
mail_activity_quick_update=True,
mail_create_nolog=True,
mail_create_nosubscribe=True,
mail_notrack=True,
no_reset_password=True,
tracking_disable=True,
)
)
# Start from a clean slate # Start from a clean slate
cls.env["mail.activity.team"].search([]).unlink() cls.env["mail.activity.team"].search([]).unlink()
# Create Users # Create Users
cls.employee = cls.env["res.users"].create( cls.employee = new_test_user(
{ cls.env,
"company_id": cls.env.ref("base.main_company").id, name="Employee",
"name": "Employee", login="csu",
"login": "csu", email="crmuser@yourcompany.com",
"email": "crmuser@yourcompany.com", groups="base.group_user,base.group_partner_manager",
"groups_id": [
(
6,
0,
[
cls.env.ref("base.group_user").id,
cls.env.ref("base.group_partner_manager").id,
],
)
],
}
) )
cls.employee2 = cls.env["res.users"].create( cls.employee2 = new_test_user(
{ cls.env,
"company_id": cls.env.ref("base.main_company").id, name="Employee 2",
"name": "Employee 2", login="csu2",
"login": "csu2", email="crmuser2@yourcompany.com",
"email": "crmuser2@yourcompany.com",
"groups_id": [(6, 0, [cls.env.ref("base.group_user").id])],
}
) )
cls.employee3 = cls.env["res.users"].create( cls.employee3 = new_test_user(
{ cls.env,
"company_id": cls.env.ref("base.main_company").id, name="Employee 3",
"name": "Employee 3", login="csu3",
"login": "csu3", email="crmuser3@yourcompany.com",
"email": "crmuser3@yourcompany.com",
"groups_id": [(6, 0, [cls.env.ref("base.group_user").id])],
}
) )
# Create Activity Types # Create Activity Types
cls.activity1 = cls.env["mail.activity.type"].create( cls.activity1 = cls.env["mail.activity.type"].create(
@ -279,7 +272,7 @@ class TestMailActivityTeam(TransactionCase):
self.assertEqual(res[0]["total_count"], 1) self.assertEqual(res[0]["total_count"], 1)
self.assertEqual(res[0]["today_count"], 2) self.assertEqual(res[0]["today_count"], 2)
res = self.env["res.users"].with_user(self.employee.id).systray_get_activities() res = self.env["res.users"].with_user(self.employee.id).systray_get_activities()
self.assertEqual(res[0]["total_count"], 2) self.assertEqual(res[0]["total_count"], 1)
def test_activity_schedule_next(self): def test_activity_schedule_next(self):
self.activity1.write( self.activity1.write(