From 50cbb70073fdc635616062bb73388e5dcf584b00 Mon Sep 17 00:00:00 2001 From: Antonio Espinosa Date: Mon, 8 Aug 2016 13:14:37 +0200 Subject: [PATCH] Link mail statistics to partner (#104) [IMP] mass_mailing_partner: Link mail statistics to partner --- mass_mailing_partner/README.rst | 15 +++++- mass_mailing_partner/__init__.py | 22 +++------ mass_mailing_partner/__openerp__.py | 14 ++++-- mass_mailing_partner/hooks.py | 37 +++++++++++++++ mass_mailing_partner/models/__init__.py | 7 ++- .../models/mail_mail_statistics.py | 37 +++++++++++++++ .../models/mail_mass_mailing.py | 5 +- .../models/mail_mass_mailing_contact.py | 8 +++- mass_mailing_partner/models/res_partner.py | 25 ++++++++-- mass_mailing_partner/tests/__init__.py | 6 ++- mass_mailing_partner/tests/base.py | 5 +- .../tests/test_mail_mail_statistics.py | 28 +++++++++++ .../tests/test_mail_mass_mailing_contact.py | 20 ++++++-- .../tests/test_partner_mail_list_wizard.py | 5 +- .../tests/test_res_partner.py | 6 ++- .../views/mail_mail_statistics_view.xml | 46 +++++++++++++++++++ .../views/mail_mass_mailing_contact_view.xml | 7 ++- .../views/mail_mass_mailing_view.xml | 4 ++ .../views/res_partner_view.xml | 15 ++++++ mass_mailing_partner/wizard/__init__.py | 5 +- .../wizard/partner_mail_list_wizard.py | 5 +- .../wizard/partner_mail_list_wizard.xml | 4 ++ 22 files changed, 284 insertions(+), 42 deletions(-) create mode 100644 mass_mailing_partner/hooks.py create mode 100644 mass_mailing_partner/models/mail_mail_statistics.py create mode 100644 mass_mailing_partner/tests/test_mail_mail_statistics.py create mode 100644 mass_mailing_partner/views/mail_mail_statistics_view.xml diff --git a/mass_mailing_partner/README.rst b/mass_mailing_partner/README.rst index 09bf2dd3..0af7934d 100644 --- a/mass_mailing_partner/README.rst +++ b/mass_mailing_partner/README.rst @@ -14,14 +14,25 @@ Features 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 Configuration ============= At first install, all existing mass mailing contacts are matched against -partners. +partners. And also mass mailing statistics are matched using model and res_id. +NOTE: When upgrading from version 1.0.0, no mass mailing statistics matching +are done, because it is done only when installing. You can execute 'partner_link' +method to all stats using odoo shell or any XML client: + +.. code:: python + + # odoo.py --addons-path= shell --config= -d + stats = self.env['mail.mail.statistics'].search([('model', '!=', False), ('res_id', '!=', False)]) + stats.partner_link() Usage ===== @@ -85,4 +96,4 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. \ No newline at end of file +To contribute to this module, please visit https://odoo-community.org. diff --git a/mass_mailing_partner/__init__.py b/mass_mailing_partner/__init__.py index 9250d91b..bc9d0590 100644 --- a/mass_mailing_partner/__init__.py +++ b/mass_mailing_partner/__init__.py @@ -1,20 +1,10 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import models from . import wizard -from openerp import api, SUPERUSER_ID - - -def _match_existing_contacts(cr, registry): - with api.Environment.manage(): - env = api.Environment(cr, SUPERUSER_ID, {}) - contact_model = env['mail.mass_mailing.contact'] - partner_model = env['res.partner'] - contacts = contact_model.search([('email', '!=', False)]) - for contact in contacts: - if contact.email: - partners = partner_model.search([('email', '=ilike', - contact.email)]) - if partners: - contact.write({'partner_id': partners[0].id}) +from .hooks import post_init_hook diff --git a/mass_mailing_partner/__openerp__.py b/mass_mailing_partner/__openerp__.py index 684b39cd..bb49d895 100644 --- a/mass_mailing_partner/__openerp__.py +++ b/mass_mailing_partner/__openerp__.py @@ -1,10 +1,15 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Link partners with mass-mailing", - "version": "8.0.1.0.0", - "author": "Antiun Ingeniería S.L., " + "version": "8.0.2.0.0", + "author": "Tecnativa, " + "Antiun Ingeniería S.L., " "Serv. Tecnol. Avanzados - Pedro M. Baeza, " "Odoo Community Association (OCA)", "license": "AGPL-3", @@ -12,8 +17,9 @@ "depends": [ 'mass_mailing', ], - "post_init_hook": "_match_existing_contacts", + "post_init_hook": "post_init_hook", 'data': [ + 'views/mail_mail_statistics_view.xml', 'views/mail_mass_mailing_contact_view.xml', 'views/mail_mass_mailing_view.xml', 'views/res_partner_view.xml', diff --git a/mass_mailing_partner/hooks.py b/mass_mailing_partner/hooks.py new file mode 100644 index 00000000..aaa37311 --- /dev/null +++ b/mass_mailing_partner/hooks.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from openerp import api, SUPERUSER_ID + +_logger = logging.getLogger(__name__) + + +def post_init_hook(cr, registry): + with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + # ACTION 1: Match existing contacts + contact_model = env['mail.mass_mailing.contact'] + partner_model = env['res.partner'] + contacts = contact_model.search([('email', '!=', False)]) + _logger.info('Trying to match %d contacts to partner by email', + len(contacts)) + for contact in contacts: + partners = partner_model.search([ + ('email', '=ilike', contact.email) + ], limit=1) + if partners: + contact.write({'partner_id': partners.id}) + # ACTION 2: Match existing statistics + stat_model = env['mail.mail.statistics'] + stats = stat_model.search([ + ('model', '!=', False), + ('res_id', '!=', False), + ]) + _logger.info('Trying to link %d mass mailing statistics to partner', + len(stats)) + stats.partner_link() diff --git a/mass_mailing_partner/models/__init__.py b/mass_mailing_partner/models/__init__.py index 744629bd..3d81de77 100644 --- a/mass_mailing_partner/models/__init__.py +++ b/mass_mailing_partner/models/__init__.py @@ -1,6 +1,11 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import mail_mass_mailing_contact from . import res_partner from . import mail_mass_mailing +from . import mail_mail_statistics diff --git a/mass_mailing_partner/models/mail_mail_statistics.py b/mass_mailing_partner/models/mail_mail_statistics.py new file mode 100644 index 00000000..dff06620 --- /dev/null +++ b/mass_mailing_partner/models/mail_mail_statistics.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class MailMailStatistics(models.Model): + _inherit = "mail.mail.statistics" + + partner_id = fields.Many2one( + string="Partner", comodel_name='res.partner', readonly=True) + + @api.model + def partner_id_from_obj(self, model, res_id): + partner_id = False + obj = self.env[model].browse(res_id) + if obj.exists(): + if model == 'res.partner': + partner_id = res_id + elif 'partner_id' in obj._fields: + partner_id = obj.partner_id.id + return partner_id + + @api.multi + def partner_link(self): + for stat in self.filtered(lambda r: r.model and r.res_id): + partner_id = self.partner_id_from_obj(stat.model, stat.res_id) + if partner_id != stat.partner_id.id: + stat.partner_id = partner_id + return True + + @api.model + def create(self, vals): + stat = super(MailMailStatistics, self).create(vals) + stat.partner_link() + return stat diff --git a/mass_mailing_partner/models/mail_mass_mailing.py b/mass_mailing_partner/models/mail_mass_mailing.py index 95d062a5..9294beb4 100644 --- a/mass_mailing_partner/models/mail_mass_mailing.py +++ b/mass_mailing_partner/models/mail_mass_mailing.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields diff --git a/mass_mailing_partner/models/mail_mass_mailing_contact.py b/mass_mailing_partner/models/mail_mass_mailing_contact.py index 04692763..7a8bf25c 100644 --- a/mass_mailing_partner/models/mail_mass_mailing_contact.py +++ b/mass_mailing_partner/models/mail_mass_mailing_contact.py @@ -1,5 +1,9 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields, api, _ @@ -49,7 +53,7 @@ class MailMassMailingContact(models.Model): def _set_partner(self, vals): email = vals.get('email', self.email) - if not email: + if not email: # pragma: no cover return vals m_mailing = self.env['mail.mass_mailing.list'] m_partner = self.env['res.partner'] diff --git a/mass_mailing_partner/models/res_partner.py b/mass_mailing_partner/models/res_partner.py index 82d7b4e2..d53b4728 100644 --- a/mass_mailing_partner/models/res_partner.py +++ b/mass_mailing_partner/models/res_partner.py @@ -1,5 +1,9 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields, api, _ from openerp.exceptions import ValidationError @@ -9,11 +13,17 @@ class ResPartner(models.Model): _inherit = 'res.partner' mass_mailing_contacts = fields.One2many( + string="Mailing lists", comodel_name='mail.mass_mailing.contact', inverse_name='partner_id') - mass_mailing_contacts_count = fields.Integer( - string='Mailing list number', compute='_count_mass_mailing_contacts', - store=True) + string='Mailing list number', + compute='_compute_mass_mailing_contacts_count', store=True) + mass_mailing_stats = fields.One2many( + string="Mass mailing stats", + comodel_name='mail.mail.statistics', inverse_name='partner_id') + mass_mailing_stats_count = fields.Integer( + string='Mass mailing stats number', + compute='_compute_mass_mailing_stats_count', store=True) @api.one @api.constrains('email') @@ -25,9 +35,14 @@ class ResPartner(models.Model): @api.one @api.depends('mass_mailing_contacts') - def _count_mass_mailing_contacts(self): + def _compute_mass_mailing_contacts_count(self): self.mass_mailing_contacts_count = len(self.mass_mailing_contacts) + @api.one + @api.depends('mass_mailing_stats') + def _compute_mass_mailing_stats_count(self): + self.mass_mailing_stats_count = len(self.mass_mailing_stats) + @api.multi def write(self, vals): res = super(ResPartner, self).write(vals) diff --git a/mass_mailing_partner/tests/__init__.py b/mass_mailing_partner/tests/__init__.py index 163ae133..57b45b37 100644 --- a/mass_mailing_partner/tests/__init__.py +++ b/mass_mailing_partner/tests/__init__.py @@ -1,5 +1,9 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import test_mail_mass_mailing_contact, test_res_partner +from . import test_mail_mail_statistics from . import test_partner_mail_list_wizard diff --git a/mass_mailing_partner/tests/base.py b/mass_mailing_partner/tests/base.py index af32621f..7832ebb2 100644 --- a/mass_mailing_partner/tests/base.py +++ b/mass_mailing_partner/tests/base.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests.common import TransactionCase diff --git a/mass_mailing_partner/tests/test_mail_mail_statistics.py b/mass_mailing_partner/tests/test_mail_mail_statistics.py new file mode 100644 index 00000000..ddec08d1 --- /dev/null +++ b/mass_mailing_partner/tests/test_mail_mail_statistics.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import base + + +class MailMailStatisticsCase(base.BaseCase): + + def test_link_partner(self): + partner = self.create_partner( + {'name': 'Test partner'}) + stat = self.env['mail.mail.statistics'].create({ + 'model': 'res.partner', + 'res_id': partner.id, + }) + self.assertEqual(partner.id, stat.partner_id.id) + + def test_link_mail_contact(self): + partner = self.create_partner( + {'name': 'Test partner', 'email': 'test@domain.com'}) + contact = self.create_mailing_contact( + {'partner_id': partner.id, 'list_id': self.mailing_list.id}) + stat = self.env['mail.mail.statistics'].create({ + 'model': 'mail.mass_mailing.contact', + 'res_id': contact.id, + }) + self.assertEqual(partner.id, stat.partner_id.id) diff --git a/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py b/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py index 05d73092..0308b766 100644 --- a/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py +++ b/mass_mailing_partner/tests/test_mail_mass_mailing_contact.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import base -from .. import _match_existing_contacts +from ..hooks import post_init_hook from psycopg2 import IntegrityError @@ -11,7 +14,7 @@ class MailMassMailingContactCase(base.BaseCase): def test_match_existing_contacts(self): contact = self.create_mailing_contact( {'email': 'partner@test.com', 'list_id': self.mailing_list.id}) - _match_existing_contacts(self.cr, self.registry) + post_init_hook(self.cr, self.registry) self.assertEqual(contact.partner_id.id, self.partner.id) def test_create_mass_mailing_contact(self): @@ -33,3 +36,14 @@ class MailMassMailingContactCase(base.BaseCase): 'list_id': self.mailing_list.id}) contact.write({'partner_id': False}) self.assertFalse(contact2.partner_id) + + def test_onchange_partner(self): + 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'}) + with self.env.do_in_onchange(): + contact.partner_id = partner + contact._onchange_partner() + self.assertEqual(contact.name, partner.name) + self.assertEqual(contact.email, partner.email) diff --git a/mass_mailing_partner/tests/test_partner_mail_list_wizard.py b/mass_mailing_partner/tests/test_partner_mail_list_wizard.py index c50d2640..3a93f669 100644 --- a/mass_mailing_partner/tests/test_partner_mail_list_wizard.py +++ b/mass_mailing_partner/tests/test_partner_mail_list_wizard.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import base from openerp.exceptions import Warning as UserError diff --git a/mass_mailing_partner/tests/test_res_partner.py b/mass_mailing_partner/tests/test_res_partner.py index a8fb2183..1d837318 100644 --- a/mass_mailing_partner/tests/test_res_partner.py +++ b/mass_mailing_partner/tests/test_res_partner.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import base from openerp.exceptions import ValidationError @@ -12,7 +15,6 @@ class ResPartnerCase(base.BaseCase): 'list_id': self.mailing_list.id}) self.create_mailing_contact({'email': 'partner@test.com', 'list_id': self.mailing_list2.id}) - self.partner._count_mass_mailing_contacts() self.assertEqual(self.partner.mass_mailing_contacts_count, 2) def test_write_res_partner(self): diff --git a/mass_mailing_partner/views/mail_mail_statistics_view.xml b/mass_mailing_partner/views/mail_mail_statistics_view.xml new file mode 100644 index 00000000..2e50e3c6 --- /dev/null +++ b/mass_mailing_partner/views/mail_mail_statistics_view.xml @@ -0,0 +1,46 @@ + + + + + + + Add partner field + mail.mail.statistics + + + + + + + + + + Add partner column + mail.mail.statistics + + + + + + + + + + Add partner search field and group by + mail.mail.statistics + + + + + + + + + + + + + diff --git a/mass_mailing_partner/views/mail_mass_mailing_contact_view.xml b/mass_mailing_partner/views/mail_mass_mailing_contact_view.xml index 37c4ccbc..4798a1f2 100644 --- a/mass_mailing_partner/views/mail_mass_mailing_contact_view.xml +++ b/mass_mailing_partner/views/mail_mass_mailing_contact_view.xml @@ -1,4 +1,9 @@ + @@ -20,7 +25,7 @@ - mail.mass_mailing.contact.search.partner + Add partner search field and group by mail.mass_mailing.contact diff --git a/mass_mailing_partner/views/mail_mass_mailing_view.xml b/mass_mailing_partner/views/mail_mass_mailing_view.xml index fff295c4..ee966359 100644 --- a/mass_mailing_partner/views/mail_mass_mailing_view.xml +++ b/mass_mailing_partner/views/mail_mass_mailing_view.xml @@ -1,4 +1,8 @@ + diff --git a/mass_mailing_partner/views/res_partner_view.xml b/mass_mailing_partner/views/res_partner_view.xml index da04ad92..3e8d5712 100644 --- a/mass_mailing_partner/views/res_partner_view.xml +++ b/mass_mailing_partner/views/res_partner_view.xml @@ -1,4 +1,9 @@ + @@ -18,6 +23,16 @@ widget="statinfo" string="Mailing lists"/> + diff --git a/mass_mailing_partner/wizard/__init__.py b/mass_mailing_partner/wizard/__init__.py index d9b71887..446dc736 100644 --- a/mass_mailing_partner/wizard/__init__.py +++ b/mass_mailing_partner/wizard/__init__.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import partner_mail_list_wizard diff --git a/mass_mailing_partner/wizard/partner_mail_list_wizard.py b/mass_mailing_partner/wizard/partner_mail_list_wizard.py index 0e6d67d0..94e1065b 100644 --- a/mass_mailing_partner/wizard/partner_mail_list_wizard.py +++ b/mass_mailing_partner/wizard/partner_mail_list_wizard.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- -# See README.rst file on addon root folder for license details +# © 2015 Pedro M. Baeza +# © 2015 Antonio Espinosa +# © 2015 Javier Iniesta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, api, fields, _ from openerp.exceptions import Warning as UserError diff --git a/mass_mailing_partner/wizard/partner_mail_list_wizard.xml b/mass_mailing_partner/wizard/partner_mail_list_wizard.xml index 28125056..94b55af7 100644 --- a/mass_mailing_partner/wizard/partner_mail_list_wizard.xml +++ b/mass_mailing_partner/wizard/partner_mail_list_wizard.xml @@ -1,4 +1,8 @@ +