From b769848f7704582cbb28b5c3f248d9bd388be426 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 | 109 +++++++++++++++--- 2 files changed, 96 insertions(+), 34 deletions(-) diff --git a/mass_mailing_partner/models/mailing_contact.py b/mass_mailing_partner/models/mailing_contact.py index e3dc618d3f..f94a829530 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: @@ -98,7 +81,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 63a91791b1..764265a549 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,13 +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_ids": [(0, 0, {"list_id": self.mailing_list2.id})], - } - ) + contact_exta = self.create_mailing_contact( + { + "email": "partner2@test.com", + "subscription_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( @@ -107,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"})