diff --git a/allow_mail_archived_partner/models/mail_thread.py b/allow_mail_archived_partner/models/mail_thread.py index f33b429..ddbd5ab 100755 --- a/allow_mail_archived_partner/models/mail_thread.py +++ b/allow_mail_archived_partner/models/mail_thread.py @@ -28,85 +28,76 @@ class MailThread(models.AbstractModel): def _notify_get_recipients(self, message, msg_vals, **kwargs): """ - Allow archived partners for ANY manual email send. + Force inclusion of archived partners for manual sends. """ _logger.error("🔥🔥🔥🔥🔥 MailThread._notify_get_recipients CALLED 🔥🔥🔥🔥🔥") - _logger.error(f"🔥 Model: {self._name}") - _logger.error(f"🔥 Message type: {getattr(message, 'message_type', 'Unknown')}") - _logger.error(f"🔥 Message subject: {getattr(message, 'subject', 'No subject')}") - _logger.error(f"🔥 Full context: {dict(self.env.context)}") - # Check MULTIPLE indicators of manual send + # Check if this is a manual send 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") or # From invoice wizard - # Additional checks for email sends - (self._name == "account.move" and - self.env.context.get("default_composition_mode") == "comment") or - (msg_vals and msg_vals.get("message_type") == "email") + self.env.context.get("force_email") or + self.env.context.get("mark_invoice_as_sent") ) _logger.error(f"🔥 Is manual send? {is_manual_send}") - _logger.error(f"🔥 All context flags: 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')}, " - f"mark_invoice_as_sent={self.env.context.get('mark_invoice_as_sent')}") + _logger.error(f"🔥 Message partner_ids: {getattr(message, 'partner_ids', None)}") - # For MANUAL sends, allow archived partners with full context - if is_manual_send: - _logger.error("🔥🔥🔥 ✓ MANUAL SEND DETECTED - Allowing archived partners 🔥🔥🔥") - _logger.error(f"🔥 Calling super() with context: active_test=False, include_archived_partners=True, mail_notify_force=True") + # For manual sends, we need to handle archived partners + if is_manual_send and hasattr(message, 'partner_ids') and message.partner_ids: + _logger.error("🔥🔥🔥 MANUAL SEND WITH PARTNERS - Handling archived partners 🔥🔥🔥") - # Use context that allows archived partners + # Get the partner IDs from the message + partner_ids = message.partner_ids.ids + _logger.error(f"🔥 Message has partners: {partner_ids}") + + # Force the lookup of THESE partners (the recipients), not the author + # We need to ensure these partners are found even if archived + + # Call parent with context that allows archived partners recipients = super( MailThread, self.with_context( active_test=False, include_archived_partners=True, mail_notify_force=True, + # Add the partner IDs we want to look up + force_notification_partner_ids=partner_ids, ) )._notify_get_recipients(message, msg_vals, **kwargs) _logger.error(f"🔥 Number of recipients found: {len(recipients)}") + + # If no recipients found, create them manually + if len(recipients) == 0 and partner_ids: + _logger.error("🔥 No recipients found, creating manually") + recipients = [] + for partner_id in partner_ids: + partner = self.env['res.partner'].with_context( + active_test=False + ).browse(partner_id) + + if partner.exists() and partner.email: + recipients.append({ + 'id': partner.id, + 'partner_id': partner.id, + 'email': partner.email, + 'name': partner.name, + 'notif': 'email', # Force email notification + 'lang': partner.lang or 'en_US', + 'type': 'customer', + 'is_follower': False, + 'groups': [], + 'notifications': [], + }) + _logger.error(f"🔥 Created recipient for archived partner: {partner.id} - {partner.email}") + for i, recipient in enumerate(recipients): _logger.error(f"🔥 Recipient {i}: partner_id={recipient.get('partner_id')}, " - f"notif={recipient.get('notif')}, email={recipient.get('email')}, " - f"groups={recipient.get('groups', [])}") + f"notif={recipient.get('notif')}, email={recipient.get('email')}") return recipients - - # 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)) or - (msg_vals and msg_vals.get("message_type") == "notification") or - getattr(message, "subtype_id", False) and - getattr(message.subtype_id, "internal", False) - ) - - if is_system_notification: - _logger.error("🔥🔥🔥 ✗ SYSTEM NOTIFICATION - Blocking emails, forcing inbox only 🔥🔥🔥") - recipients = super()._notify_get_recipients(message, msg_vals, **kwargs) - _logger.error(f"🔥 System notification recipients before blocking: {len(recipients)}") - - # Force inbox only, no email - for recipient in recipients: - recipient["notif"] = "inbox" - _logger.error(f"🔥 Blocked email for recipient: partner_id={recipient.get('partner_id')}") - - return recipients - - # Default behavior for non-manual, non-system sends - _logger.error("🔥🔥🔥 ○ DEFAULT BEHAVIOR - No special handling 🔥🔥🔥") - recipients = super()._notify_get_recipients(message, msg_vals, **kwargs) - _logger.error(f"🔥 Default recipients found: {len(recipients)}") - for i, recipient in enumerate(recipients): - _logger.error(f"🔥 Default recipient {i}: partner_id={recipient.get('partner_id')}, " - f"notif={recipient.get('notif')}") - return recipients + def _message_post(self, **kwargs): """ diff --git a/allow_mail_archived_partner/models/res_partner.py b/allow_mail_archived_partner/models/res_partner.py index 52c2e05..b6e7d40 100755 --- a/allow_mail_archived_partner/models/res_partner.py +++ b/allow_mail_archived_partner/models/res_partner.py @@ -7,98 +7,41 @@ from odoo import models, api class ResPartner(models.Model): _inherit = "res.partner" - _logger.info("=== RES.PARTNER CLASS LOADED (allow_mail_archived_partner) ===") - @api.model def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None): """ - Allow archived partners when context permits. + SIMPLE: Just remove active filters when context says to include archived. """ - _logger.error("🔥 RES.PARTNER._search CALLED 🔥") - _logger.error(f"🔥 Search args: {args}") - _logger.error(f"🔥 Context include_archived_partners: {self.env.context.get('include_archived_partners')}") - _logger.error(f"🔥 Context mail_notify_force: {self.env.context.get('mail_notify_force')}") + _logger.error("🔥 RES.PARTNER._search - Checking for archived context") _logger.error(f"🔥 Context force_email: {self.env.context.get('force_email')}") _logger.error(f"🔥 Context mark_invoice_as_sent: {self.env.context.get('mark_invoice_as_sent')}") - _logger.error(f"🔥 Context active_test: {self.env.context.get('active_test')}") + _logger.error(f"🔥 Context mail_notify_force: {self.env.context.get('mail_notify_force')}") - # Check if we should include archived partners + # Check for manual email context 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") + self.env.context.get("mark_invoice_as_sent") or + self.env.context.get("mail_notify_force") ) _logger.error(f"🔥 Should include archived? {include_archived}") if include_archived: - _logger.error("🔥🔥🔥 RES.PARTNER: CONTEXT FLAGS FOUND - Allowing archived partners 🔥🔥🔥") - - # Remove both active and partner_share filters - filtered_args = [] - for arg in args: - if isinstance(arg, (list, tuple)) and len(arg) == 3: - # Skip active filters - if arg[0] == "active": - _logger.error(f"🔥 Removing active filter: {arg}") - continue - # Skip partner_share filter for manual sends - if arg[0] == "partner_share" and arg[1] == "=" and arg[2] is True: - _logger.error(f"🔥 Removing partner_share filter: {arg}") - continue - # Also remove active in ('=', 'in', 'not in') with any value - if arg[0] == "active" and arg[1] in ("=", "in", "not in"): - _logger.error(f"🔥 Removing active filter (any value): {arg}") - continue - - filtered_args.append(arg) - - args = filtered_args + _logger.error("🔥 Removing active filters for archived partners") + # Simple: 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.error(f"🔥 Search args after cleanup: {args}") + _logger.error(f"🔥 Search args after: {args}") result = super()._search(args, offset, limit, order, count, access_rights_uid) if not count: result_ids = list(result) _logger.error(f"🔥 Search returned {len(result_ids)} results") - if result_ids: - _logger.error(f"🔥 First 3 result IDs: {result_ids[:3]}") - # Get partner details for debugging - partners = self.browse(result_ids[:3]) - for partner in partners: - _logger.error(f"🔥 Partner {partner.id}: {partner.name}, active={partner.active}, email={partner.email}") - return result - - @api.model - def _name_search(self, name='', args=None, operator='ilike', limit=100, name_get_uid=None): - """ - Also override name_search to include archived partners when context allows. - """ - _logger.error(f"🔥 RES.PARTNER._name_search CALLED: name='{name}', args={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.error("🔥 _name_search: Allowing archived partners") - # Remove active filters from args - if args is None: - args = [] - 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) - - return super()._name_search( - name=name, args=args, operator=operator, - limit=limit, name_get_uid=name_get_uid - ) \ No newline at end of file + return result \ No newline at end of file