-
-
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_partner #277
11.0 mig mass_mailing_partner #277
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.
Thanks for the work, @ernestotejeda !
One important thing you have to count with in v11 mass_mailing migrations is that the relation between contacts and lists has changed: so now there should be a contact for every mail address and that contact is subscribed to n lists.
For what this module is concerned:
- The limitation of creating a partner or not by model list may not fit quite well already. What do you think here, @yajo ?
- You should check if a contact with a partner already exists, and add the lists to the contact ones.
- Adding a contact to a list should not create a new contact if a contact associated with that partner already exists.
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.
Some complex old code is making it harder to migrate and review, so I added mostly simplification suggestions.
mass_mailing_partner/README.rst
Outdated
* Javier Iniesta <javieria@antiun.com> | ||
* Jairo Llopis <jairo.llopis@tecnativa.com> | ||
* David Vidal <david.vidal@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.
Add yourself @ernestotejeda
mass_mailing_partner/__manifest__.py
Outdated
"version": "11.0.1.0.0", | ||
"author": "Tecnativa, " | ||
"Odoo Community Association (OCA)", | ||
"website": "https://www.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.
domain=[('email', '!=', False)]) | ||
|
||
@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.
"_check_partner_id_list_ids"
]) | ||
if contact.list_ids & other_contact.mapped('list_ids'): | ||
raise ValidationError(_("Partner already exists in one of " | ||
"these mailing lists")) |
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.
Isn't it easier to just put an unique constraint on the partner_id
field? Since now a contact has several lists, there's no need to have more than 1.
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 that, you are limiting a lot the possibilities, so I prefer to not do it.
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 the same as @pedrobaeza , besides, in this way it is guaranteed that a partner is not repeated in a list and at the same time I do not limit things so much
self.name = self.partner_id.name | ||
self.email = self.partner_id.email | ||
if self.partner_id.title: | ||
self.title_id = self.partner_id.title.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.
When doing assignment with this kind of notation, it's safer to do instead:
self.title_id = self.partner_id.title
Because the ORM will check both records belong to the same model, and the rest will work equally.
|
||
@api.constrains('email') | ||
def _check_email_mass_mailing_contacts(self): | ||
for partner in 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.
Try just:
if self.sudo().filtered("mass_mailing_contact_ids.list_ids"):
raise ...
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'm thinking that it's best to not limiting this, as it will lead to constant problems
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.
email field of contact is required and it depend on the email of the partner associated. So, i think, we should not permit that someone delete the email of the partner that has some contact associated.
"mailing lists. Email must be assigned." | ||
) % partner.name) | ||
|
||
@api.multi |
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.
It's implicit, remove it.
partner.mass_mailing_contacts_count = mapped_data.get(partner.id, | ||
0) | ||
|
||
@api.multi |
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.
🔥
# Using sudo because ACLs shouldn't produce data inconsistency | ||
self.env["mail.mass_mailing.contact"].sudo().search([ | ||
("partner_id", "in", self.ids), | ||
]).write(mm_vals) |
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.
Can't you replace all of this by calling self.mass_mailing_contact_ids._onchange_partner()
after writing?
partner_mandatory = fields.Boolean(string="Mandatory Partner", | ||
default=False) | ||
partner_category = fields.Many2one(comodel_name='res.partner.category', | ||
string="Partner Tag") |
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.
Provide help on this field. Its purpose is unclear.
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.
Tested in runbot functionally 👍
Please @ernestotejeda attend @yajo and @chienandalu comments. Thanks!
It's true, now a contact has several lists, but, if we put an unique constraint on the partner_id field, then when a contact is unsubscribed, he/she will not receive any mass-mail sent to any list asociated with him/her. But with the python constraint, we can have an unsubscribed contact 'x' with a partner asociated to a sub-set of lists 'SS1', and another contact 'y' with the same partner asociated with other sub-set of lists 'SS2' but not unsubscribed. So, the email asociated with this contacts 'x' and 'y' can receive mass mailing that will be send to 'SS2' and not receive mass mailing that will be send to 'SS1'. |
ea666a2
to
471d491
Compare
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 have squashed all the v11 history for better reviewing, but there are some comments that still apply.
]) | ||
if contact.list_ids & other_contact.mapped('list_ids'): | ||
raise ValidationError(_("Partner already exists in one of " | ||
"these mailing lists")) | ||
|
||
@api.onchange('partner_id') | ||
def _onchange_partner(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.
Rename this to _onchange_partner_id_mass_mailing_partner
for having an unique method name and avoid to choke with other modules.
if not vals.get('email') and vals.get('partner_id'): | ||
vals['email'] = vals['partner_id'] | ||
result = super(MailMassMailingContact, self).create(vals) | ||
if not result.partner_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.
Please don't perform a create and a write. You should do it adding to vals the corresponding result. What you can do is:
def create(self, vals):
if not vals.get('partner_id'):
record = self.new({
'email': vals.get('email'),
'name': vals.get('name'),
})
record._set_partner(vals)
record._onchange_partner()
new_vals = record._convert_to_write(record._cache)
vals.update(new_vals)
vals = contact._set_partner(vals) | ||
vals = contact._set_name_email(vals) | ||
return super(MailMassMailingContact, self).write(vals) | ||
if not contact.partner_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.
Perform something similar to create here.
vals['email'] = partner.email | ||
vals['name'] = partner.name | ||
return vals | ||
self.partner_id = m_partner.sudo().create({ |
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.
Don't remove the _prepare_...
method for having a hook on things.
@api.constrains('partner_id', 'list_ids') | ||
def _check_partner_id_list_ids(self): | ||
for contact in self: | ||
if contact.partner_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.
I'm thinking that it's best to not limiting this, as it will lead to constant problems
|
||
@api.constrains('email') | ||
def _check_email_mass_mailing_contacts(self): | ||
for partner in 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.
I'm thinking that it's best to not limiting this, as it will lead to constant problems
It doesn't pass the tests because the module mass_mailing_custom_unsubscribe throws an error, I have done a PR #287 that solves the problem. Can you please check it? |
[IMP] mass_mailing_partner: Link mail statistics to partner
* Exclude opt_out. Now opted-out records will not be counted in the "Mailing lists" smart button in the partner form. * Avoid duplicate error. By indicating the exact `partner_id` and ensuring no contacts associated to it are found, you avoid possible duplication errors when several partners share the same name or email.
Without this patch, users without access to reading and editing mass mailing contact records are now unable to change a partner's name or email. They'd recieve an exception such as: AccessError: Sorry, you are not allowed to access this document. Only users with the following access level are currently allowed to do that: - Mass Mailing/User (Document model: mail.mass_mailing.contact) Restrictive ACLs shouldn't restrict normal user operation nor DB consistency, so using sudo mode now and testing behavior.
* [FIX+IMP] mass_mailing_list_dynamic: tests, icons, filters... * Brand new icon * Added feature of loading an existing filter as criteria * Tests as SavepointCase for optimizing times * Tests in post-install for avoiding errors on res.partner not null constraints when several modules added them. * Updated documentation. * Fix mock in test for not commiting test data. * [FIX] mass_mailing_list_dynamic: Wasn't able to create contacts in fully synced lists Syncing context was being set in the wrong object. Added to test too. * [FIX] mass_mailing_list_dynamic: Allow to write back vals from res.partner Module mass_mailing_partner writes back certain values from partner to mass_mailing_contact. Module should allow that write operation.
- In DB which use large amounts of records and intesive use of mass_mailings, not optimized compute records lead to a drastical decrease of performance
fc2fa23
to
acf27e7
Compare
I have rebased and squashed several commits. @yajo please review again to see if we unblock this. |
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.
It looks good. Some doubts, but since they are theories, I think it's not worth it blocking this for them.
if not partner.email and self.sudo().mass_mailing_contact_ids: | ||
raise ValidationError(_( | ||
"This partner '%s' is linked to one or more mass " | ||
"mailing contact. Email must be assigned." |
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'm thinking that it should discriminate when mass mailings are in queue. Otherwise, there would be no problem in removing the email, right?
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.
But the field email in the mass_mailing contact model is still required. Setting the linked partner email to blank would raise an exception.
This module links mass-mailing contacts with partners. | ||
|
||
Features | ||
-------- |
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.
Isn't this gonna crash?
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.
Yeah, good catch. The only allowed subtitle is ~~~~~~
, and I'm not sure we should keep it.
a81bd6a
to
ac6bb81
Compare
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.
As there are too much changes difficult to see if there's going to be problems, I'm merging this and we'll try on several DBs
cc @Tecnativa