From aad868624870517b50e75eb670bb52e8a49869cd Mon Sep 17 00:00:00 2001 From: Kristof Bernaert Date: Mon, 26 Jan 2026 02:25:11 +0100 Subject: [PATCH] Fix allow_mail_archived_partner causing system notifications to send emails --- .../models/mail_thread.py | 49 +++++++---- .../models/res_partner.py | 88 +++++++++---------- 2 files changed, 74 insertions(+), 63 deletions(-) diff --git a/allow_mail_archived_partner/models/mail_thread.py b/allow_mail_archived_partner/models/mail_thread.py index 9c61018..9e0ca4f 100755 --- a/allow_mail_archived_partner/models/mail_thread.py +++ b/allow_mail_archived_partner/models/mail_thread.py @@ -12,13 +12,40 @@ class MailThread(models.AbstractModel): def _notify_get_recipients(self, message, msg_vals, **kwargs): """ - FIXED: Allow archived partners ONLY for explicit manual sends + Allow archived partners ONLY for explicit manual sends """ - # 1) BLOCK system notifications completely + # 1) Check if this is a MANUAL send (from invoice wizard or compose message) + is_manual_send = ( + self.env.context.get("mail_notify_force") or + self.env.context.get("include_archived_partners") or + self.env.context.get("force_email") or # From invoice wizard + self.env.context.get("mark_invoice_as_sent") # From invoice wizard + ) + + _logger.debug(f"MailThread._notify_get_recipients for {self._name}") + _logger.debug(f"Is manual send: {is_manual_send}") + _logger.debug(f"Context: mail_notify_force={self.env.context.get('mail_notify_force')}, " + f"include_archived={self.env.context.get('include_archived_partners')}, " + f"force_email={self.env.context.get('force_email')}") + + # 2) For MANUAL sends, allow archived partners with full context + if is_manual_send: + _logger.debug(f"Manual send detected for {self._name}, allowing archived partners") + return super( + MailThread, + self.with_context( + active_test=False, + include_archived_partners=True, + mail_notify_force=True, + ) + )._notify_get_recipients(message, msg_vals, **kwargs) + + # 3) BLOCK system notifications completely is_system_notification = ( getattr(message, "message_type", None) == "notification" or getattr(message, "author_id", False) and - message.author_id == self.env.ref("base.partner_root", raise_if_not_found=False) + message.author_id == self.env.ref("base.partner_root", raise_if_not_found=False) or + (msg_vals and msg_vals.get("message_type") == "notification") ) if is_system_notification: @@ -28,20 +55,6 @@ class MailThread(models.AbstractModel): for recipient in recipients: recipient["notif"] = "inbox" return recipients - - # 2) Check if this is an EXPLICIT manual send - is_explicit_send = ( - self.env.context.get("mail_notify_force") or - self.env.context.get("include_archived_partners") - ) - # 3) For explicit sends, allow archived partners - if is_explicit_send: - _logger.debug(f"Explicit send detected for {self._name}, allowing archived partners") - return super( - MailThread, - self.with_context(active_test=False) - )._notify_get_recipients(message, msg_vals, **kwargs) - - # 4) Default behavior for non-explicit sends + # 4) Default behavior for non-manual, non-system sends return super()._notify_get_recipients(message, msg_vals, **kwargs) \ No newline at end of file diff --git a/allow_mail_archived_partner/models/res_partner.py b/allow_mail_archived_partner/models/res_partner.py index 7cbca99..63fda34 100755 --- a/allow_mail_archived_partner/models/res_partner.py +++ b/allow_mail_archived_partner/models/res_partner.py @@ -1,47 +1,45 @@ -import logging -_logger = logging.getLogger(__name__) - -from odoo import models, api - - -class ResPartner(models.Model): - _inherit = "res.partner" - - @api.model - def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None): - """ - DEBUG search method - FIXED for Odoo 16 Query object - """ - _logger.info("=== RES.PARTNER _search ===") - _logger.info(f"Search args before: {args}") - _logger.info(f"Context include_archived: {self.env.context.get('include_archived_partners')}") - _logger.info(f"Context active_test: {self.env.context.get('active_test')}") +@api.model +def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None): + """ + Allow archived partners when context permits. + """ + _logger.debug("=== RES.PARTNER _search ===") + _logger.debug(f"Search args before: {args}") + + # Check if we should include archived partners + include_archived = ( + self.env.context.get("include_archived_partners") or + self.env.context.get("mail_notify_force") or + self.env.context.get("force_email") or + self.env.context.get("mark_invoice_as_sent") + ) + + if include_archived: + _logger.debug("Context flags found - allowing archived partners") - if self.env.context.get("include_archived_partners") or self.env.context.get("mail_notify_force"): - _logger.info("Context flags found - removing active filters") - # Remove active filters - args = [ - arg for arg in args - if not ( - isinstance(arg, (list, tuple)) - and len(arg) == 3 - and arg[0] == "active" - ) - ] - self = self.with_context(active_test=False) - _logger.info(f"Search args after: {args}") + # Remove both active and partner_share filters for archived partners + filtered_args = [] + for arg in args: + # Skip active=True/False filters + if isinstance(arg, (list, tuple)) and len(arg) == 3: + if arg[0] == "active": + _logger.debug(f"Removing active filter: {arg}") + continue + # Also skip partner_share filter when looking for specific archived partners + if arg[0] == "partner_share" and arg[1] == "=" and arg[2] is True: + _logger.debug(f"Removing partner_share filter: {arg}") + continue + + filtered_args.append(arg) - # Call parent - result = super()._search(args, offset, limit, order, count, access_rights_uid) - - # FIX: Don't try to slice Query object - if not count: - # Convert to list to check results (only for debugging) - result_ids = list(result) - _logger.info(f"Search returned {len(result_ids)} results") - if result_ids: - _logger.info(f"First few result IDs: {result_ids[:10]}") - else: - _logger.info(f"Search count result: {result}") - - return result \ No newline at end of file + args = filtered_args + self = self.with_context(active_test=False) + _logger.debug(f"Search args after: {args}") + + result = super()._search(args, offset, limit, order, count, access_rights_uid) + + if not count: + result_ids = list(result) + _logger.debug(f"Search returned {len(result_ids)} results") + + return result \ No newline at end of file