diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py index 8278c76d45..45d1c9f3da 100644 --- a/mail_tracking/models/mail_message.py +++ b/mail_tracking/models/mail_message.py @@ -61,30 +61,44 @@ def _compute_is_failed_message(self): needs_action and involves_me and has_failed_trackings ) - def _search_is_failed_message(self, operator, value): + @api.model + def _search_is_failed_message(self, operator, operand): """Search for messages considered failed for the active user. Be notice that 'notificacion_ids' is a record that change if the user mark the message as readed. """ - # FIXME: Due to ORM issue with auto_join and 'OR' we construct the domain - # using an extra query to get valid results. - # For more information see: https://github.com/odoo/odoo/issues/25175 - notification_partner_ids = self.search( - [("notification_ids.res_partner_id", "=", self.env.user.partner_id.id)] + pid = self.env.user.partner_id.id + self.flush_model( + ["author_id", "mail_tracking_ids", "mail_tracking_needs_action"] + ) + self.env["mail.notification"].flush_model(["mail_message_id", "res_partner_id"]) + # retrieve failed tracking email + tracking_operator = "in" if operand else "not in" + failed_states = list(self.get_failed_states()) + tracking_ids = self.env["mail.tracking.email"]._search( + [("state", f"{tracking_operator}", failed_states)] + ) + + is_involve = expression.OR( + [ + [ + ("notification_ids.res_partner_id", "=", pid), + ], + [ + ("author_id", "=", pid), + ], + ] ) - return expression.normalize_domain( + domain = expression.AND( [ - ( - "mail_tracking_ids.state", - "in" if value else "not in", - list(self.get_failed_states()), - ), - ("mail_tracking_needs_action", "=", True), - "|", - ("author_id", "=", self.env.user.partner_id.id), - ("id", "in", notification_partner_ids.ids), + [ + ("mail_tracking_ids", "in", tracking_ids), + ("mail_tracking_needs_action", "=", True), + ], + is_involve, ] ) + return domain def _tracking_status_map_get(self): """Map tracking states to be used in chatter""" diff --git a/mail_tracking/tests/test_mail_tracking.py b/mail_tracking/tests/test_mail_tracking.py index 804b3b7cc4..2e23417d3b 100644 --- a/mail_tracking/tests/test_mail_tracking.py +++ b/mail_tracking/tests/test_mail_tracking.py @@ -714,6 +714,68 @@ def assert_tracking_tag_side_effect(*args, **kwargs): "data-odoo-tracking-email not found", tracking.error_description ) + def test_search_is_failed_message(self): + user_employee_1 = mail_new_test_user( + self.env, + groups="base.group_user", + login="employee1", + name="employee_1", + ) + partner_employee = user_employee_1.partner_id + user_employee_2 = mail_new_test_user( + self.env, + groups="base.group_user", + login="employee2", + name="employee_2", + ) + message = self.env["mail.message"].create( + { + "subject": "Message test", + "author_id": self.sender.id, + "email_from": self.sender.email, + "message_type": "comment", + "model": "res.partner", + "res_id": partner_employee.id, + "partner_ids": [Command.link(partner_employee.id)], + "body": "

This is a test message

", + } + ) + if message.is_thread_message(): + self.env[message.model].browse(message.res_id)._notify_thread(message) + # Search tracking created + tracking_email = self.env["mail.tracking.email"].search( + [ + ("mail_message_id", "=", message.id), + ("partner_id", "=", partner_employee.id), + ] + ) + # Force error state + tracking_email.state = "error" + + # employee_1 should read/search failed msg + failed_msg = message.with_user(user_employee_1).read( + fields=["is_failed_message"] + ) + self.assertTrue(failed_msg[0]["is_failed_message"]) + self.assertTrue( + self.env["mail.message"] + .with_user(user_employee_1) + .search( + [ + ("is_failed_message", "=", True), + ] + ) + ) + self.assertFalse( + self.env["mail.message"] + .with_user(user_employee_2) + .search( + [ + ("is_failed_message", "=", True), + ] + ) + ) + @tagged("-at_install", "post_install") class TestAccessTrackingEmail(HttpCaseWithUserDemo, TestMailTracking):