From b9eeff7ac74f5ed79b3f0da4728b7b6ecda0212d Mon Sep 17 00:00:00 2001
From: ernesto
Date: Tue, 2 Jul 2019 15:37:16 -0400
Subject: [PATCH] [MIG] mass_mailing_list_dynamic: Fix contact synchronization
---
mass_mailing_list_dynamic/README.rst | 5 ++-
.../models/mail_mass_mailing.py | 2 +-
.../models/mail_mass_mailing_contact.py | 14 ++++-----
.../models/mail_mass_mailing_list.py | 31 +++++++++++--------
.../readme/DESCRIPTION.rst | 3 +-
mass_mailing_list_dynamic/readme/USAGE.rst | 2 +-
.../static/description/index.html | 5 ++-
.../tests/test_dynamic_lists.py | 4 +--
8 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/mass_mailing_list_dynamic/README.rst b/mass_mailing_list_dynamic/README.rst
index bd3ac0b76..65405f6d7 100644
--- a/mass_mailing_list_dynamic/README.rst
+++ b/mass_mailing_list_dynamic/README.rst
@@ -26,8 +26,7 @@ Dynamic Mass Mailing Lists
|badge1| |badge2| |badge3| |badge4| |badge5|
Without this addon you have to choose between providing a dynamic domain and
-letting your mass mailings reach all partners that match it, or being able to
-unsubscribe to certain mailing lists while still being subscribed to others.
+letting your mass mailings reach all partners that match it.
This addon allows you to create dynamic mailing lists, so you can now benefit
from both things.
@@ -69,7 +68,7 @@ Usage
To use this module, you need to:
-#. Go to *Mass Mailing > Mailings > Mass Mailings*, and create one.
+#. Go to *Email Marketing > Mailings*, and create one.
#. Select as recipients a mailing list.
#. On "Select mailing lists:", choose one mailing list with dynamic flag
checked.
diff --git a/mass_mailing_list_dynamic/models/mail_mass_mailing.py b/mass_mailing_list_dynamic/models/mail_mass_mailing.py
index 7538360fa..e1ef350a8 100644
--- a/mass_mailing_list_dynamic/models/mail_mass_mailing.py
+++ b/mass_mailing_list_dynamic/models/mail_mass_mailing.py
@@ -10,4 +10,4 @@ class MassMailing(models.Model):
def send_mail(self):
"""Sync dynamic lists before sending mailings to them."""
self.contact_list_ids.action_sync()
- return super(MassMailing, self).send_mail()
+ return super().send_mail()
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 1d0b922b3..7ad51c01c 100644
--- a/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py
+++ b/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py
@@ -13,11 +13,9 @@ class MassMailingContact(models.Model):
def _check_no_manual_edits_on_fully_synced_lists(self):
if self.env.context.get("syncing"):
return
- for one in self:
- if any((
- list_id.dynamic and list_id.sync_method == "full"
- ) for list_id in one.mapped('list_ids')):
- raise ValidationError(
- _("""Cannot edit manually contacts in a fully synchronized list.
- Change its sync method or execute
- a manual sync instead."""))
+ 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."))
diff --git a/mass_mailing_list_dynamic/models/mail_mass_mailing_list.py b/mass_mailing_list_dynamic/models/mail_mass_mailing_list.py
index 4af9b4a92..cb0eff1a9 100644
--- a/mass_mailing_list_dynamic/models/mail_mass_mailing_list.py
+++ b/mass_mailing_list_dynamic/models/mail_mass_mailing_list.py
@@ -40,25 +40,30 @@ class MassMailingList(models.Model):
)
Partner = self.env["res.partner"]
# Skip non-dynamic lists
- dynamic = self.filtered("dynamic")
+ dynamic = self.filtered("dynamic").with_context(syncing=True)
for one in dynamic:
- sync_domain = safe_eval(one.sync_domain) + [("email", "!=", False)]
+ sync_domain = [("email", "!=", False)] + safe_eval(one.sync_domain)
desired_partners = Partner.search(sync_domain)
- # Remove undesired contacts when synchronization is full
+ # Detach or remove undesired contacts when synchronization is full
if one.sync_method == "full":
- Contact.search([
- ("list_ids", "in", one.id),
- ("partner_id", "not in", desired_partners.ids),
- ]).unlink()
- current_contacts = Contact.search([("list_ids", "in", one.id)])
- current_partners = current_contacts.mapped("partner_id")
+ contact_to_detach = one.contact_ids.filtered(
+ lambda r: r.partner_id not in desired_partners)
+ one.contact_ids -= contact_to_detach
+ contact_to_detach.filtered(lambda r: not r.list_ids).unlink()
# Add new contacts
+ current_partners = one.contact_ids.mapped('partner_id')
+ contact_to_list = self.env["mail.mass_mailing.contact"]
vals_list = []
for partner in desired_partners - current_partners:
- vals_list.append({
- "list_ids": [(4, one.id)],
- "partner_id": partner.id,
- })
+ contacts_in_partner = partner.mass_mailing_contact_ids
+ if contacts_in_partner:
+ contact_to_list |= contacts_in_partner[0]
+ else:
+ vals_list.append({
+ "list_ids": [(4, one.id)],
+ "partner_id": partner.id,
+ })
+ one.contact_ids |= contact_to_list
Contact.create(vals_list)
one.is_synced = True
# Invalidate cached contact count
diff --git a/mass_mailing_list_dynamic/readme/DESCRIPTION.rst b/mass_mailing_list_dynamic/readme/DESCRIPTION.rst
index 12e1d697b..302b147a8 100644
--- a/mass_mailing_list_dynamic/readme/DESCRIPTION.rst
+++ b/mass_mailing_list_dynamic/readme/DESCRIPTION.rst
@@ -1,6 +1,5 @@
Without this addon you have to choose between providing a dynamic domain and
-letting your mass mailings reach all partners that match it, or being able to
-unsubscribe to certain mailing lists while still being subscribed to others.
+letting your mass mailings reach all partners that match it.
This addon allows you to create dynamic mailing lists, so you can now benefit
from both things.
diff --git a/mass_mailing_list_dynamic/readme/USAGE.rst b/mass_mailing_list_dynamic/readme/USAGE.rst
index fd6130c0e..43178d2ce 100644
--- a/mass_mailing_list_dynamic/readme/USAGE.rst
+++ b/mass_mailing_list_dynamic/readme/USAGE.rst
@@ -1,6 +1,6 @@
To use this module, you need to:
-#. Go to *Mass Mailing > Mailings > Mass Mailings*, and create one.
+#. Go to *Email Marketing > Mailings*, and create one.
#. Select as recipients a mailing list.
#. On "Select mailing lists:", choose one mailing list with dynamic flag
checked.
diff --git a/mass_mailing_list_dynamic/static/description/index.html b/mass_mailing_list_dynamic/static/description/index.html
index f4e71af29..1e4cdd4c8 100644
--- a/mass_mailing_list_dynamic/static/description/index.html
+++ b/mass_mailing_list_dynamic/static/description/index.html
@@ -369,8 +369,7 @@ ul.auto-toc {
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Without this addon you have to choose between providing a dynamic domain and
-letting your mass mailings reach all partners that match it, or being able to
-unsubscribe to certain mailing lists while still being subscribed to others.
+letting your mass mailings reach all partners that match it.
This addon allows you to create dynamic mailing lists, so you can now benefit
from both things.
Table of contents
@@ -419,7 +418,7 @@ be selected.
To use this module, you need to:
-- Go to Mass Mailing > Mailings > Mass Mailings, and create one.
+- Go to Email Marketing > Mailings, and create one.
- Select as recipients a mailing list.
- On “Select mailing lists:”, choose one mailing list with dynamic flag
checked.
diff --git a/mass_mailing_list_dynamic/tests/test_dynamic_lists.py b/mass_mailing_list_dynamic/tests/test_dynamic_lists.py
index be6cc1112..93344bd1c 100644
--- a/mass_mailing_list_dynamic/tests/test_dynamic_lists.py
+++ b/mass_mailing_list_dynamic/tests/test_dynamic_lists.py
@@ -56,7 +56,7 @@ class DynamicListCase(common.SavepointCase):
# Set list as full-synced
self.list.sync_method = "full"
Contact.search([
- ("list_ids", "in", self.list.id),
+ ("list_ids", "in", self.list.ids),
("partner_id", "=", self.partners[2].id),
]).unlink()
self.list.action_sync()
@@ -69,7 +69,7 @@ class DynamicListCase(common.SavepointCase):
"partner_id": self.partners[0].id,
})
contact1 = Contact.search([
- ("list_ids", "in", self.list.id),
+ ("list_ids", "in", self.list.ids),
], limit=1)
with self.assertRaises(ValidationError):
contact1.name = "other"