From a96c42a2e3bed3a8e9ca2cb7a2c71cd316064036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Wed, 18 Mar 2026 11:06:00 +0100 Subject: [PATCH] [FIX] mass_mailing_partner: Allow multiple contacts with the same email address There should be no restrictions (similar to what happens when multiple mailing contacts are created with the same email address without this module installed). TT61525 --- .../models/mailing_contact.py | 21 +--- .../tests/test_mail_mass_mailing_contact.py | 111 +++++++++++++++--- 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/mass_mailing_partner/models/mailing_contact.py b/mass_mailing_partner/models/mailing_contact.py index 7f8ef9c632..dac37f2e57 100644 --- a/mass_mailing_partner/models/mailing_contact.py +++ b/mass_mailing_partner/models/mailing_contact.py @@ -6,8 +6,7 @@ # Copyright 2020 Hibou Corp. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError +from odoo import api, fields, models class MailingContact(models.Model): @@ -26,22 +25,6 @@ def _compute_tag_ids(self): tags = rec.partner_id.category_id rec.tag_ids = tags - @api.constrains("partner_id", "list_ids") - def _check_partner_id_list_ids(self): - for contact in self: - if contact.partner_id: - other_contact = self.search( - [ - ("partner_id", "=", contact.partner_id.id), - ("id", "!=", contact.id), - ] - ) - if contact.list_ids & other_contact.mapped("list_ids"): - raise ValidationError( - _("Partner already exists in one of these mailing lists") - + ": %s" % contact.partner_id.display_name - ) - @api.onchange("partner_id") def _onchange_partner_mass_mailing_partner(self): if self.partner_id: @@ -99,7 +82,7 @@ def _prepare_partner(self): def _set_partner(self): self.ensure_one() - if not self.email: + if not self.email or self.partner_id: return m_partner = self.env["res.partner"] # Look for a partner with that email diff --git a/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py b/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py index c67b2827c6..09fbf09284 100644 --- a/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py +++ b/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py @@ -2,15 +2,93 @@ # Copyright 2015 Antonio Espinosa # Copyright 2015 Javier Iniesta # Copyright 2020 Tecnativa - Manuel Calero +# Copyright 2025 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo.exceptions import ValidationError +from odoo.fields import Command +from odoo.tools import mute_logger from ..hooks import post_init_hook from . import base class MailMassMailingContactCase(base.BaseCase): + @mute_logger("odoo.models.unlink") + def test_mailing_contact_email(self): + partner_1 = self.env["res.partner"].create( + { + "name": "Test partner 1", + "email": "partner1@test.com", + } + ) + self.assertFalse(partner_1.mass_mailing_contact_ids) + partner_2 = self.env["res.partner"].create( + { + "name": "Test partner 2", + "email": "partner2@test.com", + } + ) + + self.assertFalse(partner_2.mass_mailing_contact_ids) + contact_1 = self.env["mailing.contact"].create( + { + "email": partner_1.email, + "partner_id": partner_1.id, + "list_ids": [Command.set(self.mailing_list.ids)], + } + ) + self.assertEqual(contact_1, partner_1.mass_mailing_contact_ids) + contact_2 = self.env["mailing.contact"].create( + { + "email": partner_2.email, + "partner_id": partner_2.id, + "list_ids": [Command.set(self.mailing_list.ids)], + } + ) + self.assertEqual(contact_2, partner_2.mass_mailing_contact_ids) + partner_2.write({"email": "partner1@test.com"}) + self.assertEqual(contact_2.email, "partner1@test.com") + contact_2.write({"list_ids": [Command.link(self.mailing_list2.id)]}) + self.assertEqual(contact_2.partner_id, partner_2) + model_mailing_list = self.env.ref("mass_mailing.model_mailing_list") + # mailing_1 + mailing_1 = self.env["mailing.mailing"].create( + { + "subject": "Test mailing 1", + "mailing_model_id": model_mailing_list.id, + "contact_list_ids": [Command.set(self.mailing_list.ids)], + } + ) + mailing_1.action_launch() + self.env.ref("mass_mailing.ir_cron_mass_mailing_queue").method_direct_trigger() + traces_1 = self.env["mailing.trace"].search( + [("mass_mailing_id", "=", mailing_1.id)] + ) + self.assertEqual(len(traces_1), 2) + traces_1_cancel = traces_1.filtered(lambda x: x.trace_status == "cancel") + self.assertEqual(len(traces_1_cancel), 1) + traces_1_sent = traces_1.filtered(lambda x: x.trace_status == "sent") + self.assertEqual(len(traces_1_sent), 1) + self.assertEqual(traces_1_sent.email, "partner1@test.com") + self.assertEqual(traces_1_sent.partner_id, partner_1) + # mailing_2 + mailing_2 = self.env["mailing.mailing"].create( + { + "subject": "Test mailing 2", + "mailing_model_id": model_mailing_list.id, + "contact_list_ids": [Command.set(self.mailing_list2.ids)], + } + ) + mailing_2.action_launch() + self.env.ref("mass_mailing.ir_cron_mass_mailing_queue").method_direct_trigger() + traces_2 = self.env["mailing.trace"].search( + [("mass_mailing_id", "=", mailing_2.id)] + ) + self.assertEqual(len(traces_2), 1) + self.assertEqual(traces_2.trace_status, "sent") + self.assertEqual(traces_2.email, "partner1@test.com") + self.assertEqual(traces_2.partner_id, partner_2) + def test_match_existing_contacts(self): contact = self.create_mailing_contact( {"email": "partner@test.com", "list_ids": [(6, 0, self.mailing_list.ids)]} @@ -35,13 +113,13 @@ def test_create_mass_mailing_contact(self): } contact = self.create_mailing_contact(contact_vals) self.check_mailing_contact_partner(contact) - with self.assertRaises(ValidationError): - self.create_mailing_contact( - { - "email": "partner2@test.com", - "list_ids": [[6, 0, [self.mailing_list2.id]]], - } - ) + contact_exta = self.create_mailing_contact( + { + "email": "partner2@test.com", + "list_ids": [[6, 0, [self.mailing_list2.id]]], + } + ) + self.check_mailing_contact_partner(contact_exta) def test_create_mass_mailing_contact_with_subscription(self): title_doctor = self.env.ref("base.res_partner_title_doctor") @@ -62,15 +140,13 @@ def test_create_mass_mailing_contact_with_subscription(self): } contact = self.create_mailing_contact(contact_vals) self.check_mailing_contact_partner(contact) - with self.assertRaises(ValidationError): - self.create_mailing_contact( - { - "email": "partner2@test.com", - "subscription_list_ids": [ - (0, 0, {"list_id": self.mailing_list2.id}) - ], - } - ) + contact_exta = self.create_mailing_contact( + { + "email": "partner2@test.com", + "subscription_list_ids": [(0, 0, {"list_id": self.mailing_list2.id})], + } + ) + self.check_mailing_contact_partner(contact_exta) def test_write_mass_mailing_contact(self): contact = self.create_mailing_contact( @@ -109,6 +185,7 @@ def test_onchange_partner(self): contact._onchange_partner_mass_mailing_partner() self.check_mailing_contact_partner(contact) + @mute_logger("odoo.models.unlink") def test_partners_merge(self): partner_1 = self.create_partner({"name": "Demo 1", "email": "demo1@demo.com"}) partner_2 = self.create_partner({"name": "Demo 2", "email": "demo2@demo.com"})