diff --git a/mail_activity_done/models/res_users.py b/mail_activity_done/models/res_users.py index 9696f53a2..05a3c4edb 100644 --- a/mail_activity_done/models/res_users.py +++ b/mail_activity_done/models/res_users.py @@ -1,6 +1,9 @@ # Copyright 2018-22 ForgeFlow +# Copyright 2023 Tecnativa - Víctor Martínez # 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): @@ -8,51 +11,61 @@ class ResUsers(models.Model): @api.model def systray_get_activities(self): - # Here we totally override the method. Not very nice, but - # we should perhaps ask Odoo to add a hook here. - 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 - AND act.done = False - GROUP BY m.id, states, act.res_model; - """ + # TODO: Simplify if Odoo allows to modify query + res = super().systray_get_activities() + # Convert list to dict + user_activities = {} + for item in res: + user_activities[item["model"]] = item + # Redo the method only with the archived records and subtract them. + query = """SELECT array_agg(res_id) as res_ids, m.id, count(*), + 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 + AND act.active = False + GROUP BY m.id, states; + """ 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() - 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() - } - - user_activities = {} - for activity in activity_data: - if not user_activities.get(activity["model"]): - user_activities[activity["model"]] = { - "name": model_names[activity["id"]], - "model": activity["model"], - "icon": modules.module.get_module_icon( - self.env[activity["model"]]._original_module - ), - "total_count": 0, - "today_count": 0, - "overdue_count": 0, - "planned_count": 0, - "type": "activity", - } - user_activities[activity["model"]][ - "%s_count" % activity["states"] - ] += activity["count"] - if activity["states"] in ("today", "overdue"): - user_activities[activity["model"]]["total_count"] += activity["count"] - + records_by_state_by_model = defaultdict( + lambda: {"today": set(), "overdue": set(), "planned": set(), "all": set()} + ) + for data in activity_data: + records_by_state_by_model[data["id"]][data["states"]] = set(data["res_ids"]) + records_by_state_by_model[data["id"]]["all"] = records_by_state_by_model[ + data["id"] + ]["all"] | set(data["res_ids"]) + for model_id in records_by_state_by_model: + model_dic = records_by_state_by_model[model_id] + model = ( + self.env["ir.model"] + .sudo() + .browse(model_id) + .with_prefetch(tuple(records_by_state_by_model.keys())) + ) + allowed_records = self.env[model.model].search( + [("id", "in", tuple(model_dic["all"]))] + ) + if not allowed_records: + continue + today = len(model_dic["today"] & set(allowed_records.ids)) + overdue = len(model_dic["overdue"] & set(allowed_records.ids)) + # Decrease total + 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()) diff --git a/mail_activity_done/tests/test_mail_activity_done.py b/mail_activity_done/tests/test_mail_activity_done.py index 1b4c8c86d..b76d00f63 100644 --- a/mail_activity_done/tests/test_mail_activity_done.py +++ b/mail_activity_done/tests/test_mail_activity_done.py @@ -1,5 +1,5 @@ # 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 odoo.tests.common import TransactionCase @@ -35,7 +35,12 @@ class TestMailActivityDoneMethods(TransactionCase): self.assertEqual(self.act1.state, "done") def test_systray_get_activities(self): - act_count = self.employee.with_user(self.employee).systray_get_activities() - self.assertEqual( - len(act_count), 1, "Number of activities should be equal to one" - ) + res = self.employee.with_user(self.employee).systray_get_activities() + self.assertEqual(res[0]["total_count"], 1) + 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)