Browse Source

[MIG] mass_mailing_partner: Migration to 11.0

pull/277/head
ernesto 6 years ago
committed by Pedro M. Baeza
parent
commit
ac6bb81a18
  1. 82
      mass_mailing_partner/README.rst
  2. 1
      mass_mailing_partner/__init__.py
  3. 5
      mass_mailing_partner/__manifest__.py
  4. 1
      mass_mailing_partner/hooks.py
  5. 1
      mass_mailing_partner/models/__init__.py
  6. 1
      mass_mailing_partner/models/mail_mail_statistics.py
  7. 1
      mass_mailing_partner/models/mail_mass_mailing.py
  8. 112
      mass_mailing_partner/models/mail_mass_mailing_contact.py
  9. 41
      mass_mailing_partner/models/res_partner.py
  10. 2
      mass_mailing_partner/readme/CONFIGURE.rst
  11. 9
      mass_mailing_partner/readme/CONTRIBUTORS.rst
  12. 11
      mass_mailing_partner/readme/DESCRIPTION.rst
  13. 3
      mass_mailing_partner/readme/USAGE.rst
  14. 1
      mass_mailing_partner/tests/__init__.py
  15. 40
      mass_mailing_partner/tests/base.py
  16. 8
      mass_mailing_partner/tests/test_mail_mail_statistics.py
  17. 57
      mass_mailing_partner/tests/test_mail_mass_mailing_contact.py
  18. 10
      mass_mailing_partner/tests/test_partner_mail_list_wizard.py
  19. 40
      mass_mailing_partner/tests/test_res_partner.py
  20. 81
      mass_mailing_partner/views/mail_mass_mailing_contact_view.xml
  21. 2
      mass_mailing_partner/views/mail_mass_mailing_view.xml
  22. 84
      mass_mailing_partner/views/res_partner_view.xml
  23. 1
      mass_mailing_partner/wizard/__init__.py
  24. 32
      mass_mailing_partner/wizard/partner_mail_list_wizard.py

82
mass_mailing_partner/README.rst

@ -1,15 +1,35 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
=============================== ===============================
Link partners with mass-mailing Link partners with mass-mailing
=============================== ===============================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github
:target: https://github.com/OCA/social/tree/11.0/mass_mailing_partner
:alt: OCA/social
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/social-11-0/social-11-0-mass_mailing_partner
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/205/11.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module links mass-mailing contacts with partners. This module links mass-mailing contacts with partners.
Features Features
--------
~~~~~~~~
* When creating or saving a mass-mailing contact, partners are matched through * When creating or saving a mass-mailing contact, partners are matched through
email, linking matched partner, or creating a new one if no match and the email, linking matched partner, or creating a new one if no match and the
maling list partner mandatory field is checked. maling list partner mandatory field is checked.
@ -17,6 +37,10 @@ Features
* Mass mailing stats smart button in partner form. * Mass mailing stats smart button in partner form.
* Filter and group by partner in mail statistics tree view * Filter and group by partner in mail statistics tree view
**Table of contents**
.. contents::
:local:
Configuration Configuration
============= =============
@ -31,44 +55,50 @@ In partner view, there is a new action called "Add to mailing list". This
action open a pop-up to select a mailing list. Selected partners will be added action open a pop-up to select a mailing list. Selected partners will be added
as mailing list contacts. as mailing list contacts.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/10.0
Bug Tracker Bug Tracker
=========== ===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/social/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Bugs are tracked on `GitHub Issues <https://github.com/OCA/social/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/social/issues/new?body=module:%20mass_mailing_partner%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits Credits
======= =======
Authors
~~~~~~~
* Tecnativa
Contributors Contributors
------------
~~~~~~~~~~~~
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Rafael Blasco <rafael.blasco@tecnativa.com>
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* Javier Iniesta <javieria@antiun.com>
* Jairo Llopis <jairo.llopis@tecnativa.com>
* David Vidal <david.vidal@tecnativa.com>
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Rafael Blasco
* Antonio Espinosa
* Javier Iniesta
* Jairo Llopis
* David Vidal
* Ernesto Tejeda
Maintainer
----------
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png .. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association :alt: Odoo Community Association
:target: https://odoo-community.org :target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use. promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.
This module is part of the `OCA/social <https://github.com/OCA/social/tree/11.0/mass_mailing_partner>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
mass_mailing_partner/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

5
mass_mailing_partner/__manifest__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015-2016 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015-2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -6,10 +5,10 @@
{ {
"name": "Link partners with mass-mailing", "name": "Link partners with mass-mailing",
"version": "10.0.1.0.3",
"version": "11.0.1.0.0",
"author": "Tecnativa, " "author": "Tecnativa, "
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",
"website": "https://www.tecnativa.com",
"website": "https://github.com/OCA/social",
"license": "AGPL-3", "license": "AGPL-3",
"category": "Marketing", "category": "Marketing",
"depends": [ "depends": [

1
mass_mailing_partner/hooks.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

1
mass_mailing_partner/models/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

1
mass_mailing_partner/models/mail_mail_statistics.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

1
mass_mailing_partner/models/mail_mass_mailing.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

112
mass_mailing_partner/models/mail_mass_mailing_contact.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -6,6 +5,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class MailMassMailingContact(models.Model): class MailMassMailingContact(models.Model):
@ -14,68 +14,84 @@ class MailMassMailingContact(models.Model):
partner_id = fields.Many2one(comodel_name='res.partner', string="Partner", partner_id = fields.Many2one(comodel_name='res.partner', string="Partner",
domain=[('email', '!=', False)]) domain=[('email', '!=', False)])
_sql_constraints = [
('partner_list_uniq', 'unique(partner_id, list_id)',
_('Partner already exists in this mailing list.'))
]
@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"))
@api.onchange('partner_id') @api.onchange('partner_id')
def _onchange_partner(self):
def _onchange_partner_mass_mailing_partner(self):
if self.partner_id: if self.partner_id:
self.name = self.partner_id.name self.name = self.partner_id.name
self.email = self.partner_id.email self.email = self.partner_id.email
self.title_id = self.partner_id.title
self.company_name = self.partner_id.company_id.name
self.country_id = self.partner_id.country_id
category_ids = self.partner_id.category_id
if category_ids:
self.tag_ids = category_ids
@api.model @api.model
@api.returns('self', lambda x: x.id)
def create(self, vals): def create(self, vals):
if not vals.get('partner_id'):
vals = self._set_partner(vals)
vals = self._set_name_email(vals)
return super(MailMassMailingContact, self).create(vals)
record = self.new(vals)
if not record.partner_id:
record._set_partner()
record._onchange_partner_mass_mailing_partner()
new_vals = record._convert_to_write(record._cache)
return super(MailMassMailingContact, self).create(new_vals)
def write(self, vals): def write(self, vals):
for contact in self: for contact in self:
if vals.get('partner_id', None) is False:
# If removing partner, search again by email
vals = contact._set_partner(vals)
vals = contact._set_name_email(vals)
return super(MailMassMailingContact, self).write(vals)
new_vals = contact.copy_data(vals)[0]
record = self.new(new_vals)
if not record.partner_id:
record._set_partner()
record._onchange_partner_mass_mailing_partner()
new_vals = record._convert_to_write(record._cache)
super(MailMassMailingContact, contact).write(new_vals)
return True
def _get_company(self):
company_id = False
if self.company_name:
company_id = self.env['res.company'].search(
[('name', '=', self.company_name)]).id
if not company_id:
company_id = self.env['res.company'].create(
{'name': self.company_name}).id
return company_id
def _prepare_partner(self, vals, mailing_list):
vals = {
'name': vals.get('name') or vals.get('email'),
'email': vals.get('email', False),
def _get_categories(self):
ca_ids = self.tag_ids.ids + self.list_ids.mapped('partner_category.id')
return [[6, 0, ca_ids]]
def _prepare_partner(self):
return {
'name': self.name or self.email,
'email': self.email,
'country_id': self.country_id.id,
'title': self.title_id.id,
'company_id': self._get_company(),
'category_id': self._get_categories(),
} }
if mailing_list.partner_category:
vals['category_id'] = [(4, mailing_list.partner_category.id, 0)]
return vals
def _set_partner(self, vals):
email = vals.get('email', self.email)
if not email: # pragma: no cover
return vals
m_mailing = self.env['mail.mass_mailing.list']
@api.multi
def _set_partner(self):
self.ensure_one()
m_partner = self.env['res.partner'] m_partner = self.env['res.partner']
list_id = vals.get('list_id', self.list_id.id)
mailing_list = m_mailing.browse(list_id)
# Look for a partner with that email # Look for a partner with that email
email = email.strip()
partners = m_partner.search([('email', '=ilike', email)], limit=1)
if partners:
email = self.email.strip()
partner = m_partner.search([('email', '=ilike', email)], limit=1)
if partner:
# Partner found # Partner found
vals['partner_id'] = partners[0].id
elif mailing_list.partner_mandatory:
self.partner_id = partner
elif self.list_ids.filtered('partner_mandatory'):
# Create partner # Create partner
partner = m_partner.sudo().create(
self._prepare_partner(vals, mailing_list))
vals['partner_id'] = partner.id
return vals
def _set_name_email(self, vals):
partner_id = vals.get('partner_id', self.partner_id.id)
if not partner_id:
return vals
partner = self.env['res.partner'].browse(partner_id)
vals['email'] = partner.email
vals['name'] = partner.name
return vals
self.partner_id = m_partner.sudo().create(self._prepare_partner())

41
mass_mailing_partner/models/res_partner.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -13,15 +12,15 @@ class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
mass_mailing_contact_ids = fields.One2many( mass_mailing_contact_ids = fields.One2many(
string="Mailing lists",
string="Mailing contacts",
oldname="mass_mailing_contacts", oldname="mass_mailing_contacts",
domain=[('opt_out', '=', False)], domain=[('opt_out', '=', False)],
comodel_name='mail.mass_mailing.contact', inverse_name='partner_id') comodel_name='mail.mass_mailing.contact', inverse_name='partner_id')
mass_mailing_contacts_count = fields.Integer( mass_mailing_contacts_count = fields.Integer(
string='Mailing list number',
string='Mailing contacts number',
compute='_compute_mass_mailing_contacts_count', store=True, compute='_compute_mass_mailing_contacts_count', store=True,
compute_sudo=True) compute_sudo=True)
mass_mailing_stats = fields.One2many(
mass_mailing_stats_ids = fields.One2many(
string="Mass mailing stats", string="Mass mailing stats",
comodel_name='mail.mail.statistics', inverse_name='partner_id') comodel_name='mail.mail.statistics', inverse_name='partner_id')
mass_mailing_stats_count = fields.Integer( mass_mailing_stats_count = fields.Integer(
@ -31,12 +30,12 @@ class ResPartner(models.Model):
@api.constrains('email') @api.constrains('email')
def _check_email_mass_mailing_contacts(self): def _check_email_mass_mailing_contacts(self):
for partner in self: for partner in self:
if partner.sudo().mass_mailing_contact_ids and not partner.email:
raise ValidationError(
_("This partner '%s' is subscribed to one or more "
"mailing lists. Email must be assigned.") % partner.name)
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."
) % partner.name)
@api.multi
@api.depends('mass_mailing_contact_ids', @api.depends('mass_mailing_contact_ids',
'mass_mailing_contact_ids.opt_out') 'mass_mailing_contact_ids.opt_out')
def _compute_mass_mailing_contacts_count(self): def _compute_mass_mailing_contacts_count(self):
@ -49,8 +48,7 @@ class ResPartner(models.Model):
partner.mass_mailing_contacts_count = mapped_data.get(partner.id, partner.mass_mailing_contacts_count = mapped_data.get(partner.id,
0) 0)
@api.multi
@api.depends('mass_mailing_stats')
@api.depends('mass_mailing_stats_ids')
def _compute_mass_mailing_stats_count(self): def _compute_mass_mailing_stats_count(self):
contact_data = self.env['mail.mail.statistics'].read_group( contact_data = self.env['mail.mail.statistics'].read_group(
[('partner_id', 'in', self.ids)], ['partner_id'], ['partner_id']) [('partner_id', 'in', self.ids)], ['partner_id'], ['partner_id'])
@ -62,12 +60,21 @@ class ResPartner(models.Model):
def write(self, vals): def write(self, vals):
res = super(ResPartner, self).write(vals) res = super(ResPartner, self).write(vals)
if vals.get('name') or vals.get('email'):
mm_vals = {}
if vals.get('name'):
mm_vals['name'] = vals['name']
if vals.get('email'):
mm_vals['email'] = vals['email']
mm_vals = {}
if vals.get('name'):
mm_vals['name'] = vals['name']
if vals.get('email'):
mm_vals['email'] = vals['email']
if vals.get('title'):
mm_vals['title_id'] = vals['title']
if vals.get('company_id'):
company = self.env['res.company'].browse(vals.get('company_id'))
mm_vals['company_name'] = company.name
if vals.get('country_id'):
mm_vals['country_id'] = vals['country_id']
if vals.get('category_id'):
mm_vals['tag_ids'] = vals['category_id']
if mm_vals:
# Using sudo because ACLs shouldn't produce data inconsistency # Using sudo because ACLs shouldn't produce data inconsistency
self.env["mail.mass_mailing.contact"].sudo().search([ self.env["mail.mass_mailing.contact"].sudo().search([
("partner_id", "in", self.ids), ("partner_id", "in", self.ids),

2
mass_mailing_partner/readme/CONFIGURE.rst

@ -0,0 +1,2 @@
At first install, all existing mass mailing contacts are matched against
partners. And also mass mailing statistics are matched using model and res_id.

9
mass_mailing_partner/readme/CONTRIBUTORS.rst

@ -0,0 +1,9 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Rafael Blasco
* Antonio Espinosa
* Javier Iniesta
* Jairo Llopis
* David Vidal
* Ernesto Tejeda

11
mass_mailing_partner/readme/DESCRIPTION.rst

@ -0,0 +1,11 @@
This module links mass-mailing contacts with partners.
Features
~~~~~~~~
* When creating or saving a mass-mailing contact, partners are matched through
email, linking matched partner, or creating a new one if no match and the
maling list partner mandatory field is checked.
* Mailing contacts smart button in partner form.
* Mass mailing stats smart button in partner form.
* Filter and group by partner in mail statistics tree view

3
mass_mailing_partner/readme/USAGE.rst

@ -0,0 +1,3 @@
In partner view, there is a new action called "Add to mailing list". This
action open a pop-up to select a mailing list. Selected partners will be added
as mailing list contacts.

1
mass_mailing_partner/tests/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

40
mass_mailing_partner/tests/base.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -10,17 +9,23 @@ from odoo.tests.common import TransactionCase
class BaseCase(TransactionCase): class BaseCase(TransactionCase):
def setUp(self): def setUp(self):
super(BaseCase, self).setUp() super(BaseCase, self).setUp()
m_partner_category = self.env['res.partner.category']
m_mailing_list = self.env['mail.mass_mailing.list']
self.company_id = self.env.ref('base.main_company')
self.company = self.env['res.company'].browse(self.company_id)
self.partner = self.create_partner({'name': 'Partner test',
'email': 'partner@test.com'})
partner_category = m_partner_category.create({'name': 'Category Test'})
self.mailing_list = m_mailing_list.create({'name': 'List test'})
self.mailing_list2 = m_mailing_list.create(
self.main_company = self.env.ref('base.main_company')
self.country_es = self.env.ref('base.es')
self.category_0 = self.env.ref('base.res_partner_category_0')
self.category_1 = self.env.ref('base.res_partner_category_1')
self.title_mister = self.env.ref('base.res_partner_title_mister')
self.partner = self.create_partner(
{'name': 'Partner test', 'email': 'partner@test.com',
'title': self.title_mister.id, 'company_id': self.main_company.id,
'country_id': self.country_es.id,
'category_id': [(6, 0, (self.category_0 | self.category_1).ids)]})
self.category_3 = self.env.ref('base.res_partner_category_3')
self.mailing_list = self.create_mailing_list({'name': 'List test'})
self.mailing_list2 = self.create_mailing_list(
{'name': 'List test 2', 'partner_mandatory': True, {'name': 'List test 2', 'partner_mandatory': True,
'partner_category': partner_category.id})
'partner_category': self.category_3.id})
def create_partner(self, vals): def create_partner(self, vals):
m_partner = self.env['res.partner'] m_partner = self.env['res.partner']
@ -30,9 +35,22 @@ class BaseCase(TransactionCase):
m_mailing_contact = self.env['mail.mass_mailing.contact'] m_mailing_contact = self.env['mail.mass_mailing.contact']
return m_mailing_contact.create(vals) return m_mailing_contact.create(vals)
def create_mailing_list(self, vals):
m_mailing_list = self.env['mail.mass_mailing.list']
return m_mailing_list.create(vals)
def check_mailing_contact_partner(self, mailing_contact): def check_mailing_contact_partner(self, mailing_contact):
if mailing_contact.partner_id: if mailing_contact.partner_id:
self.assertEqual(mailing_contact.partner_id.email, self.assertEqual(mailing_contact.partner_id.email,
mailing_contact.email) mailing_contact.email)
self.assertEqual(mailing_contact.partner_id.name, self.assertEqual(mailing_contact.partner_id.name,
mailing_contact.name) mailing_contact.name)
self.assertEqual(mailing_contact.partner_id.title,
mailing_contact.title_id)
if mailing_contact.partner_id.company_id:
self.assertEqual(mailing_contact.partner_id.company_id.name,
mailing_contact.company_name)
self.assertEqual(mailing_contact.partner_id.country_id,
mailing_contact.country_id)
self.assertEqual(mailing_contact.partner_id.category_id,
mailing_contact.tag_ids)

8
mass_mailing_partner/tests/test_mail_mail_statistics.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -21,8 +20,11 @@ class MailMailStatisticsCase(base.BaseCase):
def test_link_mail_contact(self): def test_link_mail_contact(self):
partner = self.create_partner( partner = self.create_partner(
{'name': 'Test partner', 'email': 'test@domain.com'}) {'name': 'Test partner', 'email': 'test@domain.com'})
contact = self.create_mailing_contact(
{'partner_id': partner.id, 'list_id': self.mailing_list.id})
contact_vals = {
'partner_id': partner.id,
'list_ids': [[6, 0, [self.mailing_list.id]]]
}
contact = self.create_mailing_contact(contact_vals)
stat = self.env['mail.mail.statistics'].create({ stat = self.env['mail.mail.statistics'].create({
'model': 'mail.mass_mailing.contact', 'model': 'mail.mass_mailing.contact',
'res_id': contact.id, 'res_id': contact.id,

57
mass_mailing_partner/tests/test_mail_mass_mailing_contact.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -6,44 +5,66 @@
from . import base from . import base
from ..hooks import post_init_hook from ..hooks import post_init_hook
from psycopg2 import IntegrityError
from odoo.exceptions import ValidationError
class MailMassMailingContactCase(base.BaseCase): class MailMassMailingContactCase(base.BaseCase):
def test_match_existing_contacts(self): def test_match_existing_contacts(self):
contact = self.create_mailing_contact( contact = self.create_mailing_contact(
{'email': 'partner@test.com', 'list_id': self.mailing_list.id})
{'email': 'partner@test.com',
'list_ids': [(6, 0, self.mailing_list.ids)]})
post_init_hook(self.cr, self.registry) post_init_hook(self.cr, self.registry)
self.assertEqual(contact.partner_id.id, self.partner.id) self.assertEqual(contact.partner_id.id, self.partner.id)
self.check_mailing_contact_partner(contact)
def test_create_mass_mailing_contact(self): def test_create_mass_mailing_contact(self):
contact = self.create_mailing_contact(
{'email': 'partner2@test.com', 'name': 'Partner test 2',
'list_id': self.mailing_list2.id})
title_doctor = self.env.ref('base.res_partner_title_doctor')
country_cu = self.env.ref('base.cu')
category_4 = self.env.ref('base.res_partner_category_4')
category_5 = self.env.ref('base.res_partner_category_5')
contact_vals = {
'name': 'Partner test 2', 'email': 'partner2@test.com',
'title_id': title_doctor.id, 'company_name': "TestCompany",
'country_id': country_cu.id,
'tag_ids': [(6, 0, (category_4 | category_5).ids)],
'list_ids': [(6, 0, (self.mailing_list | self.mailing_list2).ids)],
}
contact = self.create_mailing_contact(contact_vals)
self.check_mailing_contact_partner(contact) self.check_mailing_contact_partner(contact)
with self.assertRaises(IntegrityError):
self.create_mailing_contact({'email': 'partner2@test.com',
'list_id': self.mailing_list2.id})
with self.assertRaises(ValidationError):
self.create_mailing_contact(
{'email': 'partner2@test.com',
'list_ids': [[6, 0, [self.mailing_list2.id]]]})
def test_write_mass_mailing_contact(self): def test_write_mass_mailing_contact(self):
contact = self.create_mailing_contact( contact = self.create_mailing_contact(
{'email': 'partner@test.com', 'list_id': self.mailing_list.id})
{'email': 'partner@test.com',
'list_ids': [(6, 0, self.mailing_list.ids)]})
contact.write({'partner_id': False}) contact.write({'partner_id': False})
self.check_mailing_contact_partner(contact) self.check_mailing_contact_partner(contact)
contact2 = self.create_mailing_contact( contact2 = self.create_mailing_contact(
{'email': 'partner2@test.com', 'name': 'Partner test 2', {'email': 'partner2@test.com', 'name': 'Partner test 2',
'list_id': self.mailing_list.id})
contact.write({'partner_id': False})
'list_ids': [(6, 0, self.mailing_list.ids)]})
contact2.write({'partner_id': False})
self.assertFalse(contact2.partner_id) self.assertFalse(contact2.partner_id)
def test_onchange_partner(self): def test_onchange_partner(self):
contact = self.create_mailing_contact( contact = self.create_mailing_contact(
{'email': 'partner@test.com', 'list_id': self.mailing_list.id})
partner = self.create_partner(
{'name': 'Test partner', 'email': 'sample@test.com'})
{'email': 'partner@test.com',
'list_ids': [[6, 0, [self.mailing_list.id]]]})
title_doctor = self.env.ref('base.res_partner_title_doctor')
country_cu = self.env.ref('base.cu')
category_4 = self.env.ref('base.res_partner_category_4')
category_5 = self.env.ref('base.res_partner_category_5')
partner_vals = {
'name': 'Partner test 2', 'email': 'partner2@test.com',
'title': title_doctor.id, 'company_id': self.main_company.id,
'country_id': country_cu.id,
'category_id': [(6, 0, (category_4 | category_5).ids)],
}
partner = self.create_partner(partner_vals)
with self.env.do_in_onchange(): with self.env.do_in_onchange():
contact.partner_id = partner contact.partner_id = partner
contact._onchange_partner()
self.assertEqual(contact.name, partner.name)
self.assertEqual(contact.email, partner.email)
contact._onchange_partner_mass_mailing_partner()
self.check_mailing_contact_partner(contact)

10
mass_mailing_partner/tests/test_partner_mail_list_wizard.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -15,10 +14,11 @@ class PartnerMailListWizardCase(base.BaseCase):
{'mail_list_id': self.mailing_list.id}) {'mail_list_id': self.mailing_list.id})
wizard.partner_ids = [self.partner.id] wizard.partner_ids = [self.partner.id]
wizard.add_to_mail_list() wizard.add_to_mail_list()
contact = self.env['mail.mass_mailing.contact'].search([
('partner_id', '=', self.partner.id),
('list_id', '=', self.mailing_list.id)])
self.check_mailing_contact_partner(contact)
contacts = self.env['mail.mass_mailing.contact'].search([
('partner_id', '=', self.partner.id)])
cont = contacts.filtered(lambda r: wizard.mail_list_id in r.list_ids)
self.assertEqual(len(cont), 1)
self.check_mailing_contact_partner(cont)
# This line does not create a new contact # This line does not create a new contact
wizard.add_to_mail_list() wizard.add_to_mail_list()
partner = self.env['res.partner'].create({'name': 'No email partner'}) partner = self.env['res.partner'].create({'name': 'No email partner'})

40
mass_mailing_partner/tests/test_res_partner.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -11,29 +10,30 @@ from odoo.exceptions import ValidationError
class ResPartnerCase(base.BaseCase): class ResPartnerCase(base.BaseCase):
def test_count_mass_mailing_contacts(self): def test_count_mass_mailing_contacts(self):
self.create_mailing_contact({'email': 'partner@test.com',
'list_id': self.mailing_list.id})
self.create_mailing_contact({'email': 'partner@test.com',
'list_id': self.mailing_list2.id})
self.create_mailing_contact(
{'email': 'partner@test.com',
'list_ids': [[6, 0, [self.mailing_list.id]]]})
self.create_mailing_contact(
{'email': 'partner@test.com',
'list_ids': [[6, 0, [self.mailing_list2.id]]]})
self.assertEqual(self.partner.mass_mailing_contacts_count, 2) self.assertEqual(self.partner.mass_mailing_contacts_count, 2)
def test_write_res_partner(self): def test_write_res_partner(self):
user = self.env['res.users'].create({
'login': 'test',
'name': 'test',
'email': 'test@example.org',
'groups_id': [
(4, self.env.ref('base.group_user').id),
(4, self.env.ref('base.group_partner_manager').id),
]
})
contact = self.create_mailing_contact( contact = self.create_mailing_contact(
{'email': 'partner@test.com', 'list_id': self.mailing_list.id})
self.partner.sudo(user).write({
'name': 'Changed',
'email': 'partner@changed.com',
{'email': 'partner@test.com',
'list_ids': [[6, 0, [self.mailing_list.id]]]})
self.assertEqual(self.partner, contact.partner_id)
title_doctor = self.env.ref('base.res_partner_title_doctor')
country_cu = self.env.ref('base.cu')
category_4 = self.env.ref('base.res_partner_category_4')
category_5 = self.env.ref('base.res_partner_category_5')
self.partner.write({
'name': 'Changed', 'email': 'partner@changed.com',
'title': title_doctor.id, 'company_id': self.main_company.id,
'country_id': country_cu.id,
'category_id': [(6, 0, (category_4 | category_5).ids)],
}) })
self.assertEqual(contact.name, self.partner.name)
self.assertEqual(contact.email, self.partner.email)
self.check_mailing_contact_partner(contact)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
self.partner.write({'email': False}) self.partner.write({'email': False})

81
mass_mailing_partner/views/mail_mass_mailing_contact_view.xml

@ -6,37 +6,60 @@
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_tree">
<field name="name">mail.mass_mailing.contact.tree.partner</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_contact_tree"/>
<field name="arch" type="xml">
<field name="email" position="after">
<field name="partner_id"/>
</field>
<field name="email" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="name" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_tree">
<field name="name">mail.mass_mailing.contact.tree.inherit</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_contact_tree"/>
<field name="arch" type="xml">
<field name="email" position="after">
<field name="partner_id"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_form">
<field name="name">mail.mass_mailing.contact.form.partner</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_contact_form"/>
<field name="arch" type="xml">
<field name="email" position="after">
<field name="partner_id"/>
</field>
<field name="title_id" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="email" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="name" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="company_name" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="country_id" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
<field name="tag_ids" position="attributes">
<attribute name="attrs">{'readonly': [('partner_id', '!=', False)]}</attribute>
</field>
</field> </field>
</field>
</record>
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_search">
<field name="name">Add partner search field and group by</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_contact_search"/>
<field name="arch" type="xml">
<field name="email" position="after">
<field name="partner_id"/>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_search">
<field name="name">Add partner search field and group by</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_contact_search"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="partner_id"/>
</field>
<filter name="group_create_date" position="after">
<filter string="Partner"
name="group_partner"
context="{'group_by': 'partner_id'}"/>
</filter>
</field> </field>
<filter name="group_create_date" position="after">
<filter string="Partner"
name="group_partner"
context="{'group_by': 'partner_id'}"/>
</filter>
</field>
</record>
</record>
</odoo> </odoo>

2
mass_mailing_partner/views/mail_mass_mailing_view.xml

@ -10,7 +10,7 @@
<field name="model">mail.mass_mailing.list</field> <field name="model">mail.mass_mailing.list</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_list_form"/> <field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_list_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//div[@class='oe_title']" position="after">
<xpath expr="//div[hasclass('oe_title')]" position="after">
<group> <group>
<group> <group>
<field name="partner_mandatory"/> <field name="partner_mandatory"/>

84
mass_mailing_partner/views/res_partner_view.xml

@ -6,49 +6,49 @@
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">Partner Form with mailing contacts</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="groups_id" eval="[(4, ref('mass_mailing.group_mass_mailing_user'))]"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="%(mass_mailing.action_view_mass_mailing_contacts)d"
context="{'search_default_partner_id': active_id,
'default_partner_id': active_id}"
type="action"
class="oe_stat_button oe_inline"
icon="fa-envelope-o">
<field name="mass_mailing_contacts_count"
widget="statinfo"
string="Mailing lists"/>
</button>
<button name="%(mass_mailing.action_view_mail_mail_statistics)d"
context="{'search_default_partner_id': active_id,
'default_partner_id': active_id}"
type="action"
class="oe_stat_button oe_inline"
icon="fa-envelope-o">
<field name="mass_mailing_stats_count"
widget="statinfo"
string="Mass mailing stats"/>
</button>
</div>
</field>
</record>
<record model="ir.ui.view" id="view_partner_form">
<field name="name">Partner Form with mailing contacts</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="groups_id" eval="[(4, ref('mass_mailing.group_mass_mailing_user'))]"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="%(mass_mailing.action_view_mass_mailing_contacts)d"
context="{'search_default_partner_id': active_id,
'default_partner_id': active_id}"
type="action"
class="oe_stat_button oe_inline"
icon="fa-envelope-o">
<field name="mass_mailing_contacts_count"
widget="statinfo"
string="Mailing contacts"/>
</button>
<button name="%(mass_mailing.action_view_mail_mail_statistics)d"
context="{'search_default_partner_id': active_id,
'default_partner_id': active_id}"
type="action"
class="oe_stat_button oe_inline"
icon="fa-envelope-o">
<field name="mass_mailing_stats_count"
widget="statinfo"
string="Mass mailing stats"/>
</button>
</div>
</field>
</record>
<record id="view_res_partner_filter" model="ir.ui.view">
<field name="name">Partner Search with mailing contacts</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="groups_id" eval="[(4, ref('mass_mailing.group_mass_mailing_user'))]"/>
<field name="priority">20</field>
<field name="arch" type="xml">
<field name="category_id" position="after">
<field name="mass_mailing_contact_ids" string="Mailing List"
filter_domain="[('mass_mailing_contact_ids.list_id','ilike', self)]"/>
<record id="view_res_partner_filter" model="ir.ui.view">
<field name="name">Partner Search with mailing contacts</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="groups_id" eval="[(4, ref('mass_mailing.group_mass_mailing_user'))]"/>
<field name="priority">20</field>
<field name="arch" type="xml">
<field name="category_id" position="after">
<field name="mass_mailing_contact_ids" string="Mailing List"
filter_domain="[('mass_mailing_contact_ids.list_ids','ilike', self)]"/>
</field>
</field> </field>
</field>
</record>
</record>
</odoo> </odoo>

1
mass_mailing_partner/wizard/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>

32
mass_mailing_partner/wizard/partner_mail_list_wizard.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com> # Copyright 2015 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# Copyright 2015 Javier Iniesta <javieria@antiun.com> # Copyright 2015 Javier Iniesta <javieria@antiun.com>
@ -24,19 +23,18 @@ class PartnerMailListWizard(models.TransientModel):
for partner in self.partner_ids: for partner in self.partner_ids:
if not partner.email: if not partner.email:
raise UserError(_("Partner '%s' has no email.") % partner.name) raise UserError(_("Partner '%s' has no email.") % partner.name)
criteria = [
'|',
('email', '=', partner.email),
('partner_id', '=', partner.id),
('list_id', '=', self.mail_list_id.id),
]
contact_test = contact_obj.search(criteria)
if contact_test:
continue
contact_vals = {
'partner_id': partner.id,
'email': partner.email,
'name': partner.name,
'list_id': self.mail_list_id.id
}
contact_obj.create(contact_vals)
contact = contact_obj.search([('partner_id', '=', partner.id)])
if self.mail_list_id not in contact.mapped('list_ids'):
contact_vals = {
'partner_id': partner.id,
'list_ids': [[6, 0, [self.mail_list_id.id]]]
}
if partner.title:
contact_vals['title_id'] = partner.title.id
if partner.company_id:
contact_vals['company_name'] = partner.company_id.name
if partner.country_id:
contact_vals['country_id'] = partner.country_id.id
if partner.category_id:
contact_vals['tag_ids'] = partner.category_id.ids
contact_obj.create(contact_vals)
Loading…
Cancel
Save