From 11067ea9cf7f5c110b0b869646686e633b3da9af Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 29 Jul 2020 21:12:49 +0200 Subject: [PATCH] [FIX] mass_mailing_list_dynamic: Avoid error on shared contacts - Create a contact with tag "X" - Create a dynamic mailing list fully sync with criteria for tag "X". - Sync it. - Create a second mailing list non dynamic. - Try to add the contact to second mailing list. You get an error in this case, and it shouldn't happen. --- .../models/mail_mass_mailing_contact.py | 52 ++++++++++++++++--- .../tests/test_dynamic_lists.py | 14 +++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py b/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py index 7ad51c01c..8a50d2451 100644 --- a/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py +++ b/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py @@ -1,5 +1,6 @@ # Copyright 2017 Tecnativa - Jairo Llopis # Copyright 2019 Tecnativa - Victor M.M. Torres +# Copyright 2020 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import _, api, models @@ -9,13 +10,48 @@ from odoo.exceptions import ValidationError class MassMailingContact(models.Model): _inherit = "mail.mass_mailing.contact" - @api.constrains("partner_id", "list_ids", "name", "email") - def _check_no_manual_edits_on_fully_synced_lists(self): + def _check_dynamic_full_sync_list(self, mailing_list): + if mailing_list.dynamic and mailing_list.sync_method == "full": + raise ValidationError(_( + "Cannot edit manually contacts in a fully " + "synchronized list. Change its sync method or execute " + "a manual sync instead." + )) + + def _check_no_modification_on_fully_synced_lists(self, vals): + """Check that no modification is done on fully synced dynamic list. + We examine then each possible command applied in the m2m field. + """ if self.env.context.get("syncing"): return - if any(self.mapped('list_ids').filtered( - lambda x: x.dynamic and x.sync_method == "full")): - raise ValidationError( - _("Cannot edit manually contacts in a fully " - "synchronized list. Change its sync method or execute " - "a manual sync instead.")) + for command in vals["list_ids"]: + if command[0] in (1, 2, 3, 4): + lst = self.env["mail.mass_mailing.list"].browse(command[1]) + self._check_dynamic_full_sync_list(lst) + elif command[0] in (5, 6): + for lst in self.mapped("list_ids"): + self._check_dynamic_full_sync_list(lst) + if command[0] == 6: + for _id in command[2]: + lst = self.env["mail.mass_mailing.list"].browse(_id) + self._check_dynamic_full_sync_list(lst) + + @api.constrains("partner_id", "name", "email") + def _check_no_manual_edits_on_fully_synced_lists(self): + """We have to avoid also changes in linked partner, name or email.""" + if self.env.context.get("syncing"): + return + for lst in self.mapped('list_ids'): + self._check_dynamic_full_sync_list(lst) + + def write(self, vals): + if "list_ids" in vals: + self._check_no_modification_on_fully_synced_lists(vals) + return super().write(vals) + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if "list_ids" in vals: + self._check_no_modification_on_fully_synced_lists(vals) + return super().create(vals_list) diff --git a/mass_mailing_list_dynamic/tests/test_dynamic_lists.py b/mass_mailing_list_dynamic/tests/test_dynamic_lists.py index 93344bd1c..6f24648bf 100644 --- a/mass_mailing_list_dynamic/tests/test_dynamic_lists.py +++ b/mass_mailing_list_dynamic/tests/test_dynamic_lists.py @@ -136,3 +136,17 @@ class DynamicListCase(common.SavepointCase): self.assertFalse(self.list.is_synced) self.list.action_sync() self.assertTrue(self.list.is_synced) + + def test_no_edition_fully_synced_dynamic_list(self): + self.list.sync_method = "full" + contact = self.env["mail.mass_mailing.contact"].create({ + "partner_id": self.partners[0].id, + }) + with self.assertRaises(ValidationError): + contact.list_ids = [(4, self.list.id)] + # This one shouldn't fail + list2 = self.env["mail.mass_mailing.list"].create({ + "name": "test list 2", + "dynamic": False, + }) + contact.list_ids = [(4, list2.id)]