-
-
Notifications
You must be signed in to change notification settings - Fork 587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
11.0 mig mass_mailing_unique #276
Conversation
cc @Tecnativa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here there's a problem with the new Odoo mailing lists implementation as well. Here's the thing (ping @yajo ):
- Two contacts with the same email address will receive just one email, so one of them is just ignored.
- Maybe we should just add a
_sql_constraints
by email.
mass_mailing_unique/__manifest__.py
Outdated
"summary": "Avoids duplicate mailing lists and contacts", | ||
"version": "11.0.1.0.0", | ||
"category": "Marketing", | ||
"website": "https://tecnativa.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_inherit = "mail.mass_mailing.contact" | ||
|
||
@api.constrains('partner_id', 'list_ids') | ||
def _check_partner_id_lists_ids(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just add a unique constraint per email
and remove this method.
class MailMassMailingContact(models.Model): | ||
_inherit = "mail.mass_mailing.contact" | ||
|
||
@api.constrains('partner_id', 'list_ids') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not wrong, partner_id
field doesn't exist.
mass_mailing_unique/hooks.py
Outdated
cr.execute("""SELECT c.email, l.name, COUNT(c.id) | ||
FROM | ||
mail_mass_mailing_contact AS c | ||
INNER JOIN mail_mass_mailing_contact_list_rel AS cl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All you need to check, if you follow my suggestion below, is to check there are no duplicate emails in mail_mass_mailing_contact
. No joins needed.
This PR depends on @chienandalu approval. |
This can't be possible, because it would break
We just checked with @rafaelbn that it sends duplicated emails, just the 2nd (and next ones) are set in exception state. Not sure why that happens, but it can be confusing. At the end, seeing current v11 implementation, all we need here is a python constraint that avoids 2 contacts to exist for 1 list. |
the situation here is similar to 11.0 mig mass_mailing_partner #277 , i had comment about that |
@@ -0,0 +1,6 @@ | |||
* `Tecnativa <https://www.tecnativa.com>`_: | |||
|
|||
* Jairo Llopis <jairo.llopis@tecnativa.com> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove emails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think case variations should be consider to avoid duplicates due to user errors. For instance, these two email:
Are going to be sent to the same recipient, but is going to pass over the duplicates filter this module tries to avoid.
def _check_email_list_ids(self): | ||
for contact in self: | ||
other_contact = self.search([ | ||
('email', '=', contact.email), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid duplucates due to case variations:
('email', '=', contact.email.lower()),
class MailMassMailingList(models.Model): | ||
_inherit = "mail.mass_mailing.list" | ||
_sql_constraints = [ | ||
("unique_name", "UNIQUE(name)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same problem is going to happen here with case variations. For instance:
- My list of contacts
- my list of contacts
- My List Of Contacts
- MY LIST OF CONTACTS
...
They all are going to pass over the constrain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With postgre, i think you can not make an insensitive unique constraint to not distinguish between uppercase and lowercase. To solve that, we can make an UNIQUE INDEX, for example:
CREATE UNIQUE INDEX "name_unique_idx" ON "mail_mass_mailing_list" (LOWER ('name'))
But then we must catch an IntegrityError exception in the create and write method or in another place. Actually, I do not know if it's worth doing all of this for this specific case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fortunately it's possible to add a constraint case insensitive. Just put UNIQUE (LOWER(email))
. See for example: http://shuber.io/case-insensitive-unique-constraints-in-postgres/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this page it says that Unfortunately, Postgres does now allow us to define unique constraint using LOWER and according to this page one of the solutions is to make a 'UNIQUE INDEX'. That's what I said above and then it can be more work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I read it bad :(
OK, let's keep it that way. @chienandalu please give your final review
_("{0} appears {2} times in list {1}.").format(*result)) | ||
|
||
# Search for duplicates in list's name | ||
cr.execute("""SELECT name, COUNT(id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to avoid case duplicates:
SELECT LOWER(name) AS n, COUNT(id)
[...]
GROUP BY n
mass_mailing_unique/hooks.py
Outdated
errors = list() | ||
|
||
# Search for duplicates in emails | ||
cr.execute("""SELECT c.email, l.name, COUNT(c.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check avoid email case variations. Something like:
SELECT LOWER(c.email) AS e, l.name, COUNT(c.id)
[...]
GROUP BY l.name, e, c.id
@ernestotejeda please rebase and attend latest comments |
This new module avoids duplicates in mass mailing lists. Now you cannot have 2 lists with the same name, and you cannot have the same email repeated in a list. This will avoid sending the same mail to a contact repeated times, which will disturb him and most probably cause you to be blocked as spam.
45d9fef
to
5682580
Compare
@ernestotejeda next time please drop a comment when you make the rebase, because no notification gets to our inboxes if not. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yajo please finish your review with latest changes
cc @Tecnativa