Browse Source

[FIX+IMP] mass_mailing_list_dynamic: tests, icons, filters... (#211)

* [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.
pull/284/head
Pedro M. Baeza 6 years ago
parent
commit
d8fc0aff1d
  1. 24
      mass_mailing_list_dynamic/README.rst
  2. 1
      mass_mailing_list_dynamic/__init__.py
  3. 4
      mass_mailing_list_dynamic/__manifest__.py
  4. 126
      mass_mailing_list_dynamic/i18n/es.po
  5. 1
      mass_mailing_list_dynamic/models/__init__.py
  6. 6
      mass_mailing_list_dynamic/models/mail_mass_mailing_list.py
  7. 13
      mass_mailing_list_dynamic/models/res_partner.py
  8. BIN
      mass_mailing_list_dynamic/static/description/icon.png
  9. 94
      mass_mailing_list_dynamic/static/description/icon.svg
  10. 65
      mass_mailing_list_dynamic/tests/test_dynamic_lists.py
  11. 7
      mass_mailing_list_dynamic/views/mail_mass_mailing_list_view.xml
  12. 4
      mass_mailing_list_dynamic/wizards/__init__.py
  13. 23
      mass_mailing_list_dynamic/wizards/mail_mass_mailing_load_filter.py
  14. 34
      mass_mailing_list_dynamic/wizards/mail_mass_mailing_load_filter_views.xml

24
mass_mailing_list_dynamic/README.rst

@ -18,7 +18,7 @@ Configuration
To create a dynamic mailing list, you need to:
#. Go to *Mass Mailing > Mailings > Mailing Lists > Create*.
#. Go to *Mass Mailing > Mailings > Mailing Lists* and create one.
#. Check the *Dynamic* box.
#. Choose a *Sync method*:
- Leave empty to use as a manual mailing list, the normal behavior.
@ -27,10 +27,26 @@ To create a dynamic mailing list, you need to:
- *Add and remove records as needed* to make the list be fully synchronized
with the *Synchronization critera*, even if that means removing contacts
from it.
#. Define a *Synchronization critera* that will be used to match the partners
#. Define a *Synchronization criteria* that will be used to match the partners
that should go into the list as contacts. Only partners with emails will
be selected.
You can also load an existing filter over contacts:
#. Click on "Load filter" button below criteria.
#. Select one of the existing filters.
#. Click on "Load filter" and you will have that filter as criteria.
Usage
=====
#. Go to *Mass Mailing > Mailings > Mass Mailings*, and create one.
#. Select as recipients a mailing list.
#. On "Select mailing lists:", choose one mailing list with dynamic flag
checked.
#. Before sending the mass mailing, the list will be synced for having latest
changes.
Usage
=====
@ -65,13 +81,15 @@ Credits
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
* Odoo.
* FontAwesome (http://fontawesome.io).
Contributors
------------
* `Tecnativa <https://www.tecnativa.com>`_:
* Jairo Llopis <jairo.llopis@tecnativa.com>
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
Do not contact contributors directly about support or help with technical issues.

1
mass_mailing_list_dynamic/__init__.py

@ -2,3 +2,4 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models
from . import wizards

4
mass_mailing_list_dynamic/__manifest__.py

@ -4,7 +4,7 @@
{
"name": "Dynamic Mass Mailing Lists",
"summary": "Mass mailing lists that get autopopulated",
"version": "10.0.1.0.0",
"version": "10.0.1.1.0",
"category": "Marketing",
"website": "https://github.com/OCA/social",
"author": "Tecnativa, Odoo Community Association (OCA)",
@ -15,6 +15,8 @@
"mass_mailing_partner",
],
"data": [
# This should go first
"wizards/mail_mass_mailing_load_filter_views.xml",
"views/mail_mass_mailing_list_view.xml",
],
}

126
mass_mailing_list_dynamic/i18n/es.po

@ -1,21 +1,23 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mass_mailing_list_dynamic
# * mass_mailing_list_dynamic
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2017
# enjolras <yo@miguelrevilla.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-11-03 10:58+0000\n"
"PO-Revision-Date: 2017-11-03 12:00+0100\n"
"Last-Translator: Jairo Llopis <yajo.sk8@gmail.com>\n"
"Language-Team: \n"
"Language: es\n"
"POT-Creation-Date: 2018-02-26 01:46+0000\n"
"PO-Revision-Date: 2018-02-26 01:46+0000\n"
"Last-Translator: enjolras <yo@miguelrevilla.com>, 2018\n"
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 2.0.3\n"
"Content-Transfer-Encoding: \n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: mass_mailing_list_dynamic
#: model:ir.ui.view,arch_db:mass_mailing_list_dynamic.view_mail_mass_mailing_list_form
@ -23,40 +25,53 @@ msgid ""
"<i class=\"fa fa-info-circle\"/> If you want to remove contacts from a "
"dynamic list, just <b>set them as <i>Opt Out</i></b>."
msgstr ""
"<i class=\"fa fa-info-circle\"/> Si quiere eliminar contactos de una lista "
"dinámica, simplemente <b>márquelos como <i>Envío no deseado</i></b>."
#. module: mass_mailing_list_dynamic
#: model:ir.ui.view,arch_db:mass_mailing_list_dynamic.view_mail_mass_mailing_list_form
msgid ""
"<i class=\"fa fa-info-circle\"/> You cannot make manual editions of contacts "
"in fully synchronized lists."
"<i class=\"fa fa-info-circle\"/> You cannot make manual editions of contacts"
" in fully synchronized lists."
msgstr ""
"<i class=\"fa fa-info-circle\"/> No puede editar manualmente los contactos "
"en las listas que están completamente sincronizadas."
#. module: mass_mailing_list_dynamic
#: selection:mail.mass_mailing.list,sync_method:0
msgid "Add and remove records as needed"
msgstr "Añade y elimina los registros conforme se necesite"
msgstr ""
#. module: mass_mailing_list_dynamic
#: model:ir.ui.view,arch_db:mass_mailing_list_dynamic.view_mail_mass_mailing_load_filter_form
msgid "Cancel"
msgstr "Cancelar"
#. module: mass_mailing_list_dynamic
#: code:addons/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py:17
#: code:addons/mass_mailing_list_dynamic/models/mail_mass_mailing_contact.py:18
#, python-format
msgid ""
"Cannot edit manually contacts in a fully synchronized list. Change its sync "
"method or execute a manual sync instead."
msgstr ""
"No se pueden editar manualmente los contactos de una lista que está "
"completamente sincronizada. En vez de eso, cambie su método de "
"sincronización o ejecute una sincronización manual."
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,help:mass_mailing_list_dynamic.field_mail_mass_mailing_list_sync_method
msgid ""
"Choose the syncronization method for this list if you want to make it dynamic"
"Choose the syncronization method for this list if you want to make it "
"dynamic"
msgstr ""
"Escoja el método de sincronización para esta lista si quiere hacerla dinámica"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_create_uid
msgid "Created by"
msgstr "Creado por"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_create_date
msgid "Created on"
msgstr "Creado el"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_display_name
msgid "Display Name"
msgstr "Nombre mostrado"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_list_dynamic
@ -71,7 +86,39 @@ msgstr "Lista dinámica"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,help:mass_mailing_list_dynamic.field_mail_mass_mailing_list_sync_domain
msgid "Filter partners to sync in this list"
msgstr "Filtrar contactos a sincronizar en esta lista"
msgstr ""
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_filter_id
msgid "Filter to load"
msgstr ""
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_id
msgid "ID"
msgstr "ID"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter___last_update
msgid "Last Modified on"
msgstr "Última modificación e"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_load_filter_write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: mass_mailing_list_dynamic
#: model:ir.actions.act_window,name:mass_mailing_list_dynamic.action_mail_mass_mailing_load_filter
#: model:ir.ui.view,arch_db:mass_mailing_list_dynamic.view_mail_mass_mailing_list_form
#: model:ir.ui.view,arch_db:mass_mailing_list_dynamic.view_mail_mass_mailing_load_filter_form
msgid "Load filter"
msgstr "Cargar filtro"
#. module: mass_mailing_list_dynamic
#: model:ir.model,name:mass_mailing_list_dynamic.model_mail_mass_mailing_list
@ -81,17 +128,29 @@ msgstr "Lista de correo"
#. module: mass_mailing_list_dynamic
#: model:ir.model,name:mass_mailing_list_dynamic.model_mail_mass_mailing
msgid "Mass Mailing"
msgstr "Correo masivo"
msgstr "Envío masivo"
#. module: mass_mailing_list_dynamic
#: model:ir.model,name:mass_mailing_list_dynamic.model_mail_mass_mailing_contact
msgid "Mass Mailing Contact"
msgstr "Contacto de correo masivo"
msgstr "Contacto de envío masivo"
#. module: mass_mailing_list_dynamic
#: selection:mail.mass_mailing.list,sync_method:0
msgid "Only add new records"
msgstr "Solamente añadir nuevos registros"
msgstr "Añadir solo registros nuevos"
#. module: mass_mailing_list_dynamic
#: model:ir.model,name:mass_mailing_list_dynamic.model_res_partner
msgid "Partner"
msgstr "Empresa"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,help:mass_mailing_list_dynamic.field_mail_mass_mailing_list_dynamic
msgid ""
"Set this list as dynamic, to make it autosynchronized with partners from a "
"given criteria."
msgstr ""
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_list_sync_method
@ -106,14 +165,9 @@ msgstr "Sincronizar ahora"
#. module: mass_mailing_list_dynamic
#: model:ir.model.fields,field_description:mass_mailing_list_dynamic.field_mail_mass_mailing_list_sync_domain
msgid "Synchronization critera"
msgstr "Criterios de sincronización"
msgstr "Criterio de sincronización"
#~ msgid ""
#~ "<i class=\"fa fa-exclamation-circle\"/> If you manually add contacts to "
#~ "the list, <b>they might get removed later automatically!</b>"
#~ msgstr ""
#~ "<i class=\"fa fa-exclamation-circle\"/> Si añade contactos a la lista "
#~ "manualmente, <b>¡podrían ser eliminados automáticamente más tarde!</b>"
#~ msgid "Sync domain"
#~ msgstr "Dominio de sincronización"
#. module: mass_mailing_list_dynamic
#: model:ir.model,name:mass_mailing_list_dynamic.model_mail_mass_mailing_load_filter
msgid "mail.mass_mailing.load.filter"
msgstr "mail.mass_mailing.load.filter"

1
mass_mailing_list_dynamic/models/__init__.py

@ -4,3 +4,4 @@
from . import mail_mass_mailing
from . import mail_mass_mailing_contact
from . import mail_mass_mailing_list
from . import res_partner

6
mass_mailing_list_dynamic/models/mail_mass_mailing_list.py

@ -32,10 +32,12 @@ class MassMailingList(models.Model):
def action_sync(self):
"""Sync contacts in dynamic lists."""
Contact = self.env["mail.mass_mailing.contact"]
Contact = self.env["mail.mass_mailing.contact"].with_context(
syncing=True,
)
Partner = self.env["res.partner"]
# Skip non-dynamic lists
dynamic = self.filtered("dynamic").with_context(syncing=True)
dynamic = self.filtered("dynamic")
for one in dynamic:
sync_domain = safe_eval(one.sync_domain) + [("email", "!=", False)]
desired_partners = Partner.search(sync_domain)

13
mass_mailing_list_dynamic/models/res_partner.py

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models
class ResPartner(models.Model):
_inherit = 'res.partner'
def write(self, vals):
"""Allow to write values in mass mailing contact."""
return super(ResPartner, self.with_context(syncing=True)).write(vals)

BIN
mass_mailing_list_dynamic/static/description/icon.png

Before

Width: 128  |  Height: 128  |  Size: 9.2 KiB

After

Width: 128  |  Height: 128  |  Size: 5.3 KiB

94
mass_mailing_list_dynamic/static/description/icon.svg

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="icon.svg"
inkscape:export-filename="icon.png"
inkscape:export-xdpi="144"
inkscape:export-ydpi="144">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview4"
showgrid="false"
inkscape:zoom="5.9"
inkscape:cx="26.675663"
inkscape:cy="23.292293"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<rect
style="opacity:1;fill:#8c7f6c;fill-opacity:1;stroke:none;stroke-width:4.05708647;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3346"
width="80"
height="80"
x="0"
y="0" />
<path
style="fill:#675d4f;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 12.344407,43.446175 -0.11984861,56.150127 0,80 41.707315,79.760303 58.366272,62.741801 64.718248,15.042055 Z"
id="path3344"
inkscape:connector-curvature="0" />
<g
style="font-style:normal;font-weight:normal;font-size:54.74009323px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3338">
<path
d="m 66.470545,12.85352 c -0.610938,-0.427657 -1.435705,-0.458204 -2.077191,-0.06109 l -50.830086,29.32505 c -0.641486,0.366563 -1.038596,1.069143 -0.977502,1.802269 0.06109,0.763673 0.519298,1.405159 1.221877,1.680081 l 14.418149,5.895557 0,13.807211 c 0,0.79422 0.488751,1.527346 1.252424,1.832816 0.213829,0.09164 0.458204,0.122187 0.70258,0.122187 0.549844,0 1.069142,-0.213828 1.435705,-0.641485 l 9.102985,-9.988845 16.09823,6.567589 c 0.244376,0.09164 0.488751,0.152735 0.733126,0.152735 0.336017,0 0.672033,-0.09164 0.946955,-0.244376 0.519298,-0.305469 0.885861,-0.79422 0.977502,-1.374612 L 67.295312,14.808524 C 67.4175,14.04485 67.112031,13.311724 66.470545,12.85352 Z M 56.023496,58.643364 40.994408,52.503431 55.595839,28.157531 29.233841,47.677017 18.970074,43.492088 62.774367,18.229779 56.023496,58.643364 Z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:FontAwesome;-inkscape-font-specification:FontAwesome;fill:#ffffff"
id="path3342" />
</g>
<g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:37.0338974px;line-height:125%;font-family:FontAwesome;-inkscape-font-specification:FontAwesome;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3343">
<path
d="m 33.743341,24.484866 c 0,-0.723318 -0.599321,-1.322639 -1.32264,-1.322639 l -29.0980618,0 C 2.5993209,23.162227 2,23.761548 2,24.484866 l 0,2.645278 c 0,0.723319 0.5993209,1.32264 1.3226392,1.32264 l 29.0980618,0 c 0.723319,0 1.32264,-0.599321 1.32264,-1.32264 l 0,-2.645278 z m 0,-10.581114 c 0,-0.723318 -0.599321,-1.322639 -1.32264,-1.322639 l -29.0980618,0 C 2.5993209,12.581113 2,13.180434 2,13.903752 l 0,2.645279 c 0,0.723318 0.5993209,1.322639 1.3226392,1.322639 l 29.0980618,0 c 0.723319,0 1.32264,-0.599321 1.32264,-1.322639 l 0,-2.645279 z m 0,-10.5811131 c 0,-0.7233183 -0.599321,-1.3226392 -1.32264,-1.3226392 l -29.0980618,0 C 2.5993209,1.9999997 2,2.5993206 2,3.3226389 l 0,2.6452784 c 0,0.7233183 0.5993209,1.3226392 1.3226392,1.3226392 l 29.0980618,0 c 0.723319,0 1.32264,-0.5993209 1.32264,-1.3226392 l 0,-2.6452784 z"
style=""
id="path3348" />
</g>
<g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20.42372704px;line-height:125%;font-family:FontAwesome;-inkscape-font-specification:FontAwesome;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3339"
transform="matrix(0.94190867,0,0,0.94190867,26.461918,-5.3866658)">
<path
d="m 26.339767,17.049939 c 0,-0.193752 -0.15956,-0.364709 -0.364709,-0.364709 l -2.188257,0 c -0.170957,0 -0.284929,0.102574 -0.341915,0.262135 -0.193752,0.455886 -0.330518,0.888979 -0.60405,1.333468 -1.059936,1.73237 -2.940469,2.78091 -4.969165,2.78091 -1.470235,0 -2.894881,-0.569859 -3.966215,-1.57281 l 1.561412,-1.561412 c 0.136766,-0.136766 0.216546,-0.319121 0.216546,-0.512872 0,-0.398901 -0.330518,-0.729419 -0.729419,-0.729419 l -5.1059315,0 c -0.3989009,0 -0.7294188,0.330518 -0.7294188,0.729419 l 0,5.105931 c 0,0.398901 0.3305179,0.729419 0.7294188,0.729419 0.1937515,0 0.3761065,-0.07978 0.5128725,-0.216546 l 1.470235,-1.470235 c 1.618398,1.538618 3.772463,2.4162 5.994911,2.4162 4.205555,0 7.533529,-2.815101 8.502288,-6.849699 0.0114,-0.02279 0.0114,-0.05699 0.0114,-0.07978 z m 0.284929,-9.1177352 c 0,-0.3989009 -0.330517,-0.7294188 -0.729418,-0.7294188 -0.193752,0 -0.376107,0.07978 -0.512873,0.2165462 L 23.900773,8.889566 C 22.282375,7.3623454 20.105516,6.4733662 17.871671,6.4733662 c -4.205556,0 -7.567721,2.8037036 -8.5478772,6.8496988 0,0.02279 0,0.05699 0,0.07978 0,0.193752 0.1595603,0.364709 0.3647094,0.364709 l 2.2680368,0 c 0.170957,0 0.284929,-0.102574 0.341915,-0.262134 0.193752,-0.455887 0.330518,-0.88898 0.60405,-1.333469 1.059937,-1.73237 2.940469,-2.7809095 4.969166,-2.7809095 1.470234,0 2.894881,0.5584613 3.977612,1.5614125 l -1.57281,1.572809 c -0.136766,0.136766 -0.216546,0.319121 -0.216546,0.512873 0,0.398901 0.330518,0.729418 0.729419,0.729418 l 5.105932,0 c 0.398901,0 0.729418,-0.330517 0.729418,-0.729418 l 0,-5.1059322 z"
id="path3351"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
</g>
</svg>

65
mass_mailing_list_dynamic/tests/test_dynamic_lists.py

@ -4,32 +4,35 @@
from mock import patch
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
from odoo.tests import common
class DynamicListCase(TransactionCase):
def setUp(self):
super(DynamicListCase, self).setUp()
self.tag = self.env["res.partner.category"].create({
@common.at_install(False)
@common.post_install(True)
class DynamicListCase(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(DynamicListCase, cls).setUpClass()
cls.tag = cls.env["res.partner.category"].create({
"name": "testing tag",
})
self.partners = self.env["res.partner"]
cls.partners = cls.env["res.partner"]
for number in range(5):
self.partners |= self.partners.create({
cls.partners |= cls.partners.create({
"name": "partner %d" % number,
"category_id": [(4, self.tag.id, False)],
"category_id": [(4, cls.tag.id, False)],
"email": "%d@example.com" % number,
})
self.list = self.env["mail.mass_mailing.list"].create({
cls.list = cls.env["mail.mass_mailing.list"].create({
"name": "test list",
"dynamic": True,
"sync_domain": repr([("category_id", "in", self.tag.ids)]),
"sync_domain": repr([("category_id", "in", cls.tag.ids)]),
})
self.mail = self.env["mail.mass_mailing"].create({
cls.mail = cls.env["mail.mass_mailing"].create({
"name": "test mass mailing",
"contact_list_ids": [(4, self.list.id, False)],
"contact_list_ids": [(4, cls.list.id, False)],
})
self.mail._onchange_model_and_list()
cls.mail._onchange_model_and_list()
def test_list_sync(self):
"""List is synced correctly."""
@ -53,6 +56,10 @@ class DynamicListCase(TransactionCase):
self.assertTrue(contact0.exists())
# Set list as full-synced
self.list.sync_method = "full"
Contact.search([
("list_id", "=", self.list.id),
("partner_id", "=", self.partners[2].id),
]).unlink()
self.list.action_sync()
self.assertEqual(self.list.contact_nbr, 3)
self.assertFalse(contact0.exists())
@ -73,7 +80,7 @@ class DynamicListCase(TransactionCase):
contact1.partner_id = self.partners[0]
def test_sync_when_sending_mail(self):
"""Dynamic list is synced before mailing to it."""
"""Check that list in synced when sending a mass mailing."""
self.list.action_sync()
self.assertEqual(self.list.contact_nbr, 5)
# Create a new partner
@ -82,9 +89,31 @@ class DynamicListCase(TransactionCase):
"category_id": [(4, self.tag.id, False)],
"email": "extra@example.com",
})
# Before sending the mail, the list is updated
with patch("odoo.addons.base.ir.ir_mail_server"
".IrMailServer.send_email") as send_email:
# Mock sending low level method, because an auto-commit happens there
with patch("odoo.addons.mail.models.mail_mail.MailMail.send") as s:
self.mail.send_mail()
self.assertEqual(6, send_email.call_count)
self.assertEqual(1, s.call_count)
self.assertEqual(6, self.list.contact_nbr)
def test_load_filter(self):
domain = "[('id', '=', 1)]"
ir_filter = self.env['ir.filters'].create({
'name': 'Test filter',
'model_id': 'res.partner',
'domain': domain,
})
wizard = self.env['mail.mass_mailing.load.filter'].with_context(
active_id=self.list.id,
).create({
'filter_id': ir_filter.id,
})
wizard.load_filter()
self.assertEqual(self.list.sync_domain, domain)
def test_change_partner(self):
self.list.sync_method = 'full'
self.list.action_sync()
# This shouldn't fail
self.partners[:1].write({
'email': 'test_mass_mailing_list_dynamic@example.org',
})

7
mass_mailing_list_dynamic/views/mail_mass_mailing_list_view.xml

@ -52,6 +52,13 @@
options='{"model": "res.partner"}'
/>
</group>
<button
name="%(action_mail_mass_mailing_load_filter)d"
type="action"
string="Load filter"
icon="fa-filter"
colspan="1"
/>
</group>
</xpath>
</field>

4
mass_mailing_list_dynamic/wizards/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import mail_mass_mailing_load_filter

23
mass_mailing_list_dynamic/wizards/mail_mass_mailing_load_filter.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class MassMailingLoadFilter(models.TransientModel):
_name = "mail.mass_mailing.load.filter"
filter_id = fields.Many2one(
comodel_name='ir.filters',
string="Filter to load",
required=True,
domain=[('model_id', '=', 'res.partner')],
)
def load_filter(self):
self.ensure_one()
mass_list = self.env['mail.mass_mailing.list'].browse(
self.env.context['active_id']
)
mass_list.sync_domain = self.filter_id.domain

34
mass_mailing_list_dynamic/wizards/mail_mass_mailing_load_filter_views.xml

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 Tecnativa - Pedro M. Baea
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_mail_mass_mailing_load_filter_form" model="ir.ui.view">
<field name="model">mail.mass_mailing.load.filter</field>
<field name="arch" type="xml">
<form>
<group>
<field name="filter_id"/>
</group>
<footer>
<button name="load_filter"
string="Load filter"
type="object"
/>
<button special="cancel"
string="Cancel"
/>
</footer>
</form>
</field>
</record>
<act_window id="action_mail_mass_mailing_load_filter"
name="Load filter"
res_model="mail.mass_mailing.load.filter"
target="new"
view_mode="form"
/>
</odoo>
Loading…
Cancel
Save