Browse Source

Link mail statistics to partner (#104)

[IMP] mass_mailing_partner: Link mail statistics to partner
pull/277/head
Antonio Espinosa 8 years ago
committed by Pedro M. Baeza
parent
commit
50cbb70073
  1. 15
      mass_mailing_partner/README.rst
  2. 22
      mass_mailing_partner/__init__.py
  3. 14
      mass_mailing_partner/__openerp__.py
  4. 37
      mass_mailing_partner/hooks.py
  5. 7
      mass_mailing_partner/models/__init__.py
  6. 37
      mass_mailing_partner/models/mail_mail_statistics.py
  7. 5
      mass_mailing_partner/models/mail_mass_mailing.py
  8. 8
      mass_mailing_partner/models/mail_mass_mailing_contact.py
  9. 25
      mass_mailing_partner/models/res_partner.py
  10. 6
      mass_mailing_partner/tests/__init__.py
  11. 5
      mass_mailing_partner/tests/base.py
  12. 28
      mass_mailing_partner/tests/test_mail_mail_statistics.py
  13. 20
      mass_mailing_partner/tests/test_mail_mass_mailing_contact.py
  14. 5
      mass_mailing_partner/tests/test_partner_mail_list_wizard.py
  15. 6
      mass_mailing_partner/tests/test_res_partner.py
  16. 46
      mass_mailing_partner/views/mail_mail_statistics_view.xml
  17. 7
      mass_mailing_partner/views/mail_mass_mailing_contact_view.xml
  18. 4
      mass_mailing_partner/views/mail_mass_mailing_view.xml
  19. 15
      mass_mailing_partner/views/res_partner_view.xml
  20. 5
      mass_mailing_partner/wizard/__init__.py
  21. 5
      mass_mailing_partner/wizard/partner_mail_list_wizard.py
  22. 4
      mass_mailing_partner/wizard/partner_mail_list_wizard.xml

15
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=<addons_path_list> shell --config=<odoo_config_file> -d <database>
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.
To contribute to this module, please visit https://odoo-community.org.

22
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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

14
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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',

37
mass_mailing_partner/hooks.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# © 2015 Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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()

7
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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

37
mass_mailing_partner/models/mail_mail_statistics.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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

5
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import models, fields

8
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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']

25
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# 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)

6
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# 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

5
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.tests.common import TransactionCase

28
mass_mailing_partner/tests/test_mail_mail_statistics.py

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# 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)

20
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# 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)

5
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import base
from openerp.exceptions import Warning as UserError

6
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# 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):

46
mass_mailing_partner/views/mail_mail_statistics_view.xml

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<openerp>
<data>
<record model="ir.ui.view" id="view_mail_mail_statistics_form">
<field name="name">Add partner field</field>
<field name="model">mail.mail.statistics</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mail_statistics_form"/>
<field name="arch" type="xml">
<field name="res_id" position="after">
<field name="partner_id"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_mail_mail_statistics_tree">
<field name="name">Add partner column</field>
<field name="model">mail.mail.statistics</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mail_statistics_tree"/>
<field name="arch" type="xml">
<field name="sent" position="before">
<field name="partner_id"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_mail_mail_statistics_search">
<field name="name">Add partner search field and group by</field>
<field name="model">mail.mail.statistics</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mail_statistics_search"/>
<field name="arch" type="xml">
<field name="mass_mailing_id" position="after">
<field name="partner_id"/>
</field>
<filter name="group_reply_date" position="after">
<filter string="Partner"
name="group_partner"
context="{'group_by': 'partner_id'}"/>
</filter>
</field>
</record>
</data>
</openerp>

7
mass_mailing_partner/views/mail_mass_mailing_contact_view.xml

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2015 Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
© 2015 Antonio Espinosa <antonioea@antiun.com>
© 2015 Javier Iniesta <javieria@antiun.com>
© 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<openerp>
<data>
@ -20,7 +25,7 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_search">
<field name="name">mail.mass_mailing.contact.search.partner</field>
<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">

4
mass_mailing_partner/views/mail_mass_mailing_view.xml

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2015 Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
© 2015 Antonio Espinosa <antonioea@antiun.com>
© 2015 Javier Iniesta <javieria@antiun.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<openerp>
<data>

15
mass_mailing_partner/views/res_partner_view.xml

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2015 Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
© 2015 Antonio Espinosa <antonioea@antiun.com>
© 2015 Javier Iniesta <javieria@antiun.com>
© 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<openerp>
<data>
@ -18,6 +23,16 @@
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>

5
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import partner_mail_list_wizard

5
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 <pedro.baeza@serviciosbaeza.com>
# © 2015 Antonio Espinosa <antonioea@antiun.com>
# © 2015 Javier Iniesta <javieria@antiun.com>
# 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

4
mass_mailing_partner/wizard/partner_mail_list_wizard.xml

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2015 Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
© 2015 Antonio Espinosa <antonioea@antiun.com>
© 2015 Javier Iniesta <javieria@antiun.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<openerp>
<data>

Loading…
Cancel
Save