mirror of https://github.com/OCA/social.git
[add] mail_digest
parent
1516e65e64
commit
600648a9f0
|
@ -0,0 +1,90 @@
|
||||||
|
.. 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
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Mail digest notifications
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
This module allows users/partners to:
|
||||||
|
|
||||||
|
* select "digest" mode in their notification settings
|
||||||
|
* with digest mode on select a frequency: "daily" or "weekly"
|
||||||
|
* configure specific rules per message subtype (enabled/disabled)
|
||||||
|
|
||||||
|
to receive or to not receive any email notification for a given subtype.
|
||||||
|
|
||||||
|
The preference tab on user's form will look like:
|
||||||
|
|
||||||
|
.. image:: ./images/preview.png
|
||||||
|
|
||||||
|
|
||||||
|
Behavior
|
||||||
|
--------
|
||||||
|
|
||||||
|
When a partner with digest mode on is notified with a message of type email or an email
|
||||||
|
all the messages are collected inside a `mail.digest` container.
|
||||||
|
|
||||||
|
A daily cron and a weekly cron will take care of creating a single email per each digest,
|
||||||
|
which will be sent as a standard email.
|
||||||
|
|
||||||
|
If the message has a specific subtype, all of this will work only
|
||||||
|
if personal settings allow to receive notification for that specific subtype.
|
||||||
|
Specifically:
|
||||||
|
|
||||||
|
* no record for type: message passes
|
||||||
|
* record disabled for type: message don't pass
|
||||||
|
* record enabled for type: message pass
|
||||||
|
|
||||||
|
NOTE: under the hood the digest notification logic excludes followers to be notified,
|
||||||
|
since you really want to notify only mail.digest's partner.
|
||||||
|
|
||||||
|
Known issues / Roadmap
|
||||||
|
======================
|
||||||
|
|
||||||
|
* take full control of message and email template.
|
||||||
|
|
||||||
|
Right now the notification message and the digest mail itself is wrapped inside Odoo mail template.
|
||||||
|
We should be able to customize this easily.
|
||||||
|
|
||||||
|
|
||||||
|
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 smashing it by providing a detailed and welcomed feedback.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
|
||||||
|
|
||||||
|
Funders
|
||||||
|
-------
|
||||||
|
|
||||||
|
The development of this module has been financially supported by: `Fluxdock.io <https://fluxdock.io>`_
|
||||||
|
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. image:: https://odoo-community.org/logo.png
|
||||||
|
:alt: Odoo Community Association
|
||||||
|
:target: https://odoo-community.org
|
||||||
|
|
||||||
|
This module is maintained by the OCA.
|
||||||
|
|
||||||
|
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 https://odoo-community.org.
|
|
@ -0,0 +1 @@
|
||||||
|
from . import models
|
|
@ -0,0 +1,22 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
{
|
||||||
|
'name': 'Mail digest',
|
||||||
|
'summary': """Basic digest mail handling.""",
|
||||||
|
'version': '9.0.1.0.0',
|
||||||
|
'license': 'AGPL-3',
|
||||||
|
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
||||||
|
'depends': [
|
||||||
|
'mail',
|
||||||
|
],
|
||||||
|
'data': [
|
||||||
|
'data/ir_cron.xml',
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'views/mail_digest_views.xml',
|
||||||
|
'views/partner_views.xml',
|
||||||
|
'views/user_views.xml',
|
||||||
|
'templates/digest_default.xml',
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
<record forcecreate="True" id="ir_cron_mail_digest_daily_action" model="ir.cron">
|
||||||
|
<field name="name">Digest mail process - daily</field>
|
||||||
|
<field name="user_id" ref="base.user_root"/>
|
||||||
|
<field name="interval_number">1</field>
|
||||||
|
<field name="interval_type">days</field>
|
||||||
|
<field name="numbercall">-1</field>
|
||||||
|
<field eval="False" name="doall"/>
|
||||||
|
<field eval="'mail.digest'" name="model"/>
|
||||||
|
<field eval="'process'" name="function"/>
|
||||||
|
<field eval="'()'" name="args"/>
|
||||||
|
</record>
|
||||||
|
<record forcecreate="True" id="ir_cron_mail_digest_weekly_action" model="ir.cron">
|
||||||
|
<field name="name">Digest mail process - weekly</field>
|
||||||
|
<field name="user_id" ref="base.user_root"/>
|
||||||
|
<field name="interval_number">1</field>
|
||||||
|
<field name="interval_type">weeks</field>
|
||||||
|
<field name="numbercall">-1</field>
|
||||||
|
<field eval="False" name="doall"/>
|
||||||
|
<field eval="'mail.digest'" name="model"/>
|
||||||
|
<field eval="'process'" name="function"/>
|
||||||
|
<field eval="'(\'weekly\',)'" name="args"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<template id="view_email_template_corporate_identity">
|
||||||
|
<body>
|
||||||
|
<html>
|
||||||
|
<img style="float: right" t-attf-src="data:image;base64,{{env.user.company_id.logo}}" />
|
||||||
|
<!-- if some template calling us sets this variable,
|
||||||
|
we print a h1 tag /-->
|
||||||
|
<h1 t-if="email_heading"><t t-esc="email_heading" /></h1>
|
||||||
|
<t t-raw="0" />
|
||||||
|
<!-- use some standard footer if the user doesn't have
|
||||||
|
a signature /-->
|
||||||
|
<footer t-if="not email_use_user_signature">
|
||||||
|
<p>
|
||||||
|
<a t-att-href="env.user.company_id.website">
|
||||||
|
<t t-esc="env.user.company_id.name" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p><t t-esc="env.user.company_id.phone" /></p>
|
||||||
|
</footer>
|
||||||
|
<footer t-if="email_use_user_signature">
|
||||||
|
<t t-raw="env.user.signature" />
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
|
</body>
|
||||||
|
</template>
|
||||||
|
<template id="view_email_template_demo1">
|
||||||
|
<!-- because we can simply call the ci here, we don't need to
|
||||||
|
repeat it /-->
|
||||||
|
<t t-call="email_template_qweb.view_email_template_corporate_identity">
|
||||||
|
<!-- the template we call uses this as title if we set it /-->
|
||||||
|
<t t-set="email_heading" t-value="email_template.subject" />
|
||||||
|
<h2>Dear <t t-esc="object.name" />,</h2>
|
||||||
|
<p>
|
||||||
|
This is an email template using qweb.
|
||||||
|
</p>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="email_template_demo1" model="mail.template">
|
||||||
|
<field name="name">QWeb demo</field>
|
||||||
|
<field name="body_type">qweb</field>
|
||||||
|
<field name="body_view_id" ref="view_email_template_demo1" />
|
||||||
|
<field name="model_id" ref="base.model_res_users" />
|
||||||
|
<field name="subject">QWeb demo email</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
|
@ -0,0 +1,184 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * mail_digest
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 9.0c\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2017-05-23 07:08+0000\n"
|
||||||
|
"PO-Revision-Date: 2017-04-27 16:55+0200\n"
|
||||||
|
"Last-Translator: <>\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"Language: de\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 1.8.9\n"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_create_uid
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_create_uid
|
||||||
|
msgid "Created by"
|
||||||
|
msgstr "Angelegt von"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_create_date
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_create_date
|
||||||
|
msgid "Created on"
|
||||||
|
msgstr "Angelegt am"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: selection:res.partner,notify_frequency:0
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr "Täglich"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/mail_digest.py:106
|
||||||
|
msgid "Daily update"
|
||||||
|
msgstr "täglich Übersicht"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/res_partner.py:11
|
||||||
|
#: model:ir.actions.act_window,name:mail_digest.action_digest_all
|
||||||
|
#: model:ir.ui.menu,name:mail_digest.menu_email_digest
|
||||||
|
#, python-format
|
||||||
|
msgid "Digest"
|
||||||
|
msgstr "Übersicht"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_display_name
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_display_name
|
||||||
|
msgid "Display Name"
|
||||||
|
msgstr "Angezeigter Name"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_enabled
|
||||||
|
msgid "Enabled"
|
||||||
|
msgstr "Aktivieren"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_frequency
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_notify_frequency
|
||||||
|
msgid "Frequency"
|
||||||
|
msgstr "Häufigkeit"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.default_digest_tmpl
|
||||||
|
msgid "Hello,"
|
||||||
|
msgstr "Guten Tag"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_id
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_id
|
||||||
|
msgid "ID"
|
||||||
|
msgstr "ID"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest___last_update
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf___last_update
|
||||||
|
msgid "Last Modified on"
|
||||||
|
msgstr "Zuletzt geändert am"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_write_uid
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_write_uid
|
||||||
|
msgid "Last Updated by"
|
||||||
|
msgstr "Zuletzt aktualisiert durch"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_write_date
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_write_date
|
||||||
|
msgid "Last Updated on"
|
||||||
|
msgstr "Zuletzt aktualisiert am"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_mail_id
|
||||||
|
msgid "Mail"
|
||||||
|
msgstr "E-Mail"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_form
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_tree
|
||||||
|
msgid "Mail digest"
|
||||||
|
msgstr "Übersicht"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_message_ids
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_form
|
||||||
|
msgid "Messages"
|
||||||
|
msgstr "Mitteilungen"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_name
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Bezeichnung"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.notification_form
|
||||||
|
msgid "Notification"
|
||||||
|
msgstr "Benachrichtigung"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_subtype_id
|
||||||
|
msgid "Notification type"
|
||||||
|
msgstr "Benachrichtigung"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_notify_conf_ids
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.notification_tree
|
||||||
|
msgid "Notifications"
|
||||||
|
msgstr "Benachrichtigungen"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_res_partner
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_partner_id
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_partner_id
|
||||||
|
msgid "Partner"
|
||||||
|
msgstr "Partner"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_disabled_notify_subtype_ids
|
||||||
|
msgid "Partner disabled subtypes"
|
||||||
|
msgstr "Partner disabled subtypes"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_enabled_notify_subtype_ids
|
||||||
|
msgid "Partner enabled subtypes"
|
||||||
|
msgstr "Partner enabled subtypes"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_partner_notification_conf
|
||||||
|
msgid "Partner notification configuration"
|
||||||
|
msgstr "Partner notification configuration"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_state
|
||||||
|
msgid "Status"
|
||||||
|
msgstr "Status"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: selection:res.partner,notify_frequency:0
|
||||||
|
msgid "Weekly"
|
||||||
|
msgstr "Wöchentlich"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/mail_digest.py:108
|
||||||
|
msgid "Weekly update"
|
||||||
|
msgstr "wöchentlich Übersicht"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: sql_constraint:partner.notification.conf:0
|
||||||
|
msgid "You can have only one configuration per subtype!"
|
||||||
|
msgstr "You can have only one configuration per subtype!"
|
||||||
|
|
||||||
|
#~ msgid "Mail notification"
|
||||||
|
#~ msgstr "Mail notification"
|
||||||
|
|
||||||
|
#~ msgid "Mail notifications control panel"
|
||||||
|
#~ msgstr "Mail notifications control panel"
|
||||||
|
|
||||||
|
#~ msgid "Message subtypes"
|
||||||
|
#~ msgstr "Nachrichten-Subtyp"
|
|
@ -0,0 +1,175 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * mail_digest
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 9.0c\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2017-05-23 07:08+0000\n"
|
||||||
|
"PO-Revision-Date: 2017-05-23 07:08+0000\n"
|
||||||
|
"Last-Translator: <>\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_create_uid
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_create_uid
|
||||||
|
msgid "Created by"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_create_date
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_create_date
|
||||||
|
msgid "Created on"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: selection:res.partner,notify_frequency:0
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/mail_digest.py:106
|
||||||
|
#, python-format
|
||||||
|
msgid "Daily update"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/res_partner.py:11
|
||||||
|
#: model:ir.actions.act_window,name:mail_digest.action_digest_all
|
||||||
|
#: model:ir.ui.menu,name:mail_digest.menu_email_digest
|
||||||
|
#, python-format
|
||||||
|
msgid "Digest"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_display_name
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_display_name
|
||||||
|
msgid "Display Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_enabled
|
||||||
|
msgid "Enabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_frequency
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_notify_frequency
|
||||||
|
msgid "Frequency"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.default_digest_tmpl
|
||||||
|
msgid "Hello,"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_id
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_id
|
||||||
|
msgid "ID"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest___last_update
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf___last_update
|
||||||
|
msgid "Last Modified on"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_write_uid
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_write_uid
|
||||||
|
msgid "Last Updated by"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_write_date
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_write_date
|
||||||
|
msgid "Last Updated on"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_mail_id
|
||||||
|
msgid "Mail"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_form
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_tree
|
||||||
|
msgid "Mail digest"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_message_ids
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.mail_digest_form
|
||||||
|
msgid "Messages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_name
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.notification_form
|
||||||
|
msgid "Notification"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_subtype_id
|
||||||
|
msgid "Notification type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_notify_conf_ids
|
||||||
|
#: model:ir.ui.view,arch_db:mail_digest.notification_tree
|
||||||
|
msgid "Notifications"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_res_partner
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_partner_id
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_partner_notification_conf_partner_id
|
||||||
|
msgid "Partner"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_disabled_notify_subtype_ids
|
||||||
|
msgid "Partner disabled subtypes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_res_partner_enabled_notify_subtype_ids
|
||||||
|
msgid "Partner enabled subtypes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model,name:mail_digest.model_partner_notification_conf
|
||||||
|
msgid "Partner notification configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: model:ir.model.fields,field_description:mail_digest.field_mail_digest_state
|
||||||
|
msgid "Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: selection:res.partner,notify_frequency:0
|
||||||
|
msgid "Weekly"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: code:addons/mail_digest/models/mail_digest.py:108
|
||||||
|
#, python-format
|
||||||
|
msgid "Weekly update"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: mail_digest
|
||||||
|
#: sql_constraint:partner.notification.conf:0
|
||||||
|
msgid "You can have only one configuration per subtype!"
|
||||||
|
msgstr ""
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,2 @@
|
||||||
|
from . import mail_digest
|
||||||
|
from . import res_partner
|
|
@ -0,0 +1,183 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from openerp import fields, models, api, _
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger('[mail_digest]')
|
||||||
|
|
||||||
|
|
||||||
|
class MailDigest(models.Model):
|
||||||
|
_name = 'mail.digest'
|
||||||
|
_description = 'Mail digest'
|
||||||
|
_order = 'create_date desc'
|
||||||
|
|
||||||
|
name = fields.Char(
|
||||||
|
string="Name",
|
||||||
|
compute="_compute_name",
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
|
# maybe we can retrieve the from messages?
|
||||||
|
partner_id = fields.Many2one(
|
||||||
|
string='Partner',
|
||||||
|
comodel_name='res.partner',
|
||||||
|
readonly=True,
|
||||||
|
required=True,
|
||||||
|
ondelete='cascade',
|
||||||
|
)
|
||||||
|
frequency = fields.Selection(
|
||||||
|
related='partner_id.notify_frequency',
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
|
message_ids = fields.Many2many(
|
||||||
|
comodel_name='mail.message',
|
||||||
|
string='Messages'
|
||||||
|
)
|
||||||
|
# TODO: take care of `auto_delete` feature
|
||||||
|
mail_id = fields.Many2one(
|
||||||
|
'mail.mail',
|
||||||
|
'Mail',
|
||||||
|
ondelete='set null',
|
||||||
|
)
|
||||||
|
state = fields.Selection(related='mail_id.state')
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
@api.depends("partner_id", "partner_id.notify_frequency")
|
||||||
|
def _compute_name(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.name = u'{} - {}'.format(
|
||||||
|
rec.partner_id.name, rec._get_subject())
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create_or_update(self, partners, message, subtype_id=None):
|
||||||
|
subtype_id = subtype_id or message.subtype_id
|
||||||
|
for partner in partners:
|
||||||
|
digest = self._get_or_create_by_partner(partner, message)
|
||||||
|
digest.message_ids |= message
|
||||||
|
return True
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_by_partner(self, partner, mail_id=False):
|
||||||
|
domain = [
|
||||||
|
('partner_id', '=', partner.id),
|
||||||
|
('mail_id', '=', mail_id),
|
||||||
|
]
|
||||||
|
return self.search(domain, limit=1)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_or_create_by_partner(self, partner, message=None, mail_id=False):
|
||||||
|
existing = self._get_by_partner(partner, mail_id=mail_id)
|
||||||
|
if existing:
|
||||||
|
return existing
|
||||||
|
values = {'partner_id': partner.id, }
|
||||||
|
return self.create(values)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _message_group_by_key(self, msg):
|
||||||
|
return msg.subtype_id.id
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _message_group_by(self):
|
||||||
|
self.ensure_one()
|
||||||
|
grouped = {}
|
||||||
|
for msg in self.message_ids:
|
||||||
|
grouped.setdefault(self._message_group_by_key(msg), []).append(msg)
|
||||||
|
return grouped
|
||||||
|
|
||||||
|
def _get_template(self):
|
||||||
|
# TODO: move this to a configurable field
|
||||||
|
return self.env.ref('mail_digest.default_digest_tmpl')
|
||||||
|
|
||||||
|
def _get_site_name(self):
|
||||||
|
# default to company
|
||||||
|
name = self.env.user.company_id.name
|
||||||
|
if 'website' in self.env:
|
||||||
|
try:
|
||||||
|
ws = self.env['website'].get_current_website()
|
||||||
|
except RuntimeError:
|
||||||
|
# RuntimeError: object unbound -> no website request
|
||||||
|
ws = None
|
||||||
|
if ws:
|
||||||
|
name = ws.name
|
||||||
|
return name
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _get_subject(self):
|
||||||
|
# TODO: shall we move this to computed field?
|
||||||
|
self.ensure_one()
|
||||||
|
subject = self._get_site_name() + ' '
|
||||||
|
if self.partner_id.notify_frequency == 'daily':
|
||||||
|
subject += _('Daily update')
|
||||||
|
elif self.partner_id.notify_frequency == 'weekly':
|
||||||
|
subject += _('Weekly update')
|
||||||
|
return subject
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _get_template_values(self):
|
||||||
|
self.ensure_one()
|
||||||
|
subject = self._get_subject()
|
||||||
|
template_values = {
|
||||||
|
'digest': self,
|
||||||
|
'subject': subject,
|
||||||
|
'grouped_messages': self._message_group_by(),
|
||||||
|
'base_url':
|
||||||
|
self.env['ir.config_parameter'].get_param('web.base.url'),
|
||||||
|
}
|
||||||
|
return template_values
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _get_email_values(self, template=None):
|
||||||
|
self.ensure_one()
|
||||||
|
template = template or self._get_template()
|
||||||
|
subject = self._get_subject()
|
||||||
|
template_values = self._get_template_values()
|
||||||
|
values = {
|
||||||
|
'email_from': self.env.user.company_id.email,
|
||||||
|
'recipient_ids': [(4, self.partner_id.id)],
|
||||||
|
'subject': subject,
|
||||||
|
'body_html': template.with_context(
|
||||||
|
**self._template_context()
|
||||||
|
).render(template_values),
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
|
||||||
|
def _create_mail_context(self):
|
||||||
|
return {
|
||||||
|
'notify_only_recipients': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _template_context(self):
|
||||||
|
self.ensure_one()
|
||||||
|
return {
|
||||||
|
'lang': self.partner_id.lang,
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def create_email(self, template=None):
|
||||||
|
mail_model = self.env['mail.mail'].with_context(
|
||||||
|
**self._create_mail_context())
|
||||||
|
created = []
|
||||||
|
for item in self:
|
||||||
|
if not item.message_ids:
|
||||||
|
# useless to create a mail for a digest w/ messages
|
||||||
|
# messages could be deleted by admin for instance.
|
||||||
|
continue
|
||||||
|
values = item.with_context(
|
||||||
|
**item._template_context()
|
||||||
|
)._get_email_values(template=template)
|
||||||
|
item.mail_id = mail_model.create(values)
|
||||||
|
created.append(item.id)
|
||||||
|
if created:
|
||||||
|
logger.info('Create email for digest IDS=%s', str(created))
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def process(self, frequency='daily', domain=None):
|
||||||
|
if not domain:
|
||||||
|
domain = [
|
||||||
|
('mail_id', '=', False),
|
||||||
|
('partner_id.notify_frequency', '=', frequency),
|
||||||
|
]
|
||||||
|
self.search(domain).create_email()
|
|
@ -0,0 +1,208 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from openerp import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class ResPartner(models.Model):
|
||||||
|
_inherit = 'res.partner'
|
||||||
|
|
||||||
|
notify_email = fields.Selection(selection_add=[('digest', _('Digest'))])
|
||||||
|
notify_frequency = fields.Selection(
|
||||||
|
string='Frequency',
|
||||||
|
selection=[
|
||||||
|
('daily', 'Daily'),
|
||||||
|
('weekly', 'Weekly')
|
||||||
|
],
|
||||||
|
default='weekly',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
notify_conf_ids = fields.One2many(
|
||||||
|
string='Notifications',
|
||||||
|
inverse_name='partner_id',
|
||||||
|
comodel_name='partner.notification.conf',
|
||||||
|
)
|
||||||
|
enabled_notify_subtype_ids = fields.Many2many(
|
||||||
|
string='Partner enabled subtypes',
|
||||||
|
comodel_name='mail.message.subtype',
|
||||||
|
compute='_compute_enabled_notify_subtype_ids',
|
||||||
|
search='_search_enabled_notify_subtype_ids',
|
||||||
|
)
|
||||||
|
disabled_notify_subtype_ids = fields.Many2many(
|
||||||
|
string='Partner disabled subtypes',
|
||||||
|
comodel_name='mail.message.subtype',
|
||||||
|
compute='_compute_disabled_notify_subtype_ids',
|
||||||
|
search='_search_disabled_notify_subtype_ids',
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _compute_notify_subtypes(self, enabled):
|
||||||
|
self.ensure_one()
|
||||||
|
query = (
|
||||||
|
'SELECT subtype_id FROM partner_notification_conf '
|
||||||
|
'WHERE partner_id=%s AND enabled = %s'
|
||||||
|
)
|
||||||
|
self.env.cr.execute(
|
||||||
|
query, (self.id, enabled))
|
||||||
|
return [x[0] for x in self.env.cr.fetchall()]
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
@api.depends('notify_conf_ids.subtype_id')
|
||||||
|
def _compute_enabled_notify_subtype_ids(self):
|
||||||
|
for partner in self:
|
||||||
|
partner.enabled_notify_subtype_ids = \
|
||||||
|
partner._compute_notify_subtypes(True)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
@api.depends('notify_conf_ids.subtype_id')
|
||||||
|
def _compute_disabled_notify_subtype_ids(self):
|
||||||
|
for partner in self:
|
||||||
|
partner.disabled_notify_subtype_ids = \
|
||||||
|
partner._compute_notify_subtypes(False)
|
||||||
|
|
||||||
|
def _search_notify_subtype_ids_domain(self, operator, value, enabled):
|
||||||
|
if operator in ('in', 'not in') and \
|
||||||
|
not isinstance(value, (tuple, list)):
|
||||||
|
value = [value, ]
|
||||||
|
conf_value = value
|
||||||
|
if isinstance(conf_value, int):
|
||||||
|
# we search conf records always w/ 'in'
|
||||||
|
conf_value = [conf_value]
|
||||||
|
_value = self.env['partner.notification.conf'].search([
|
||||||
|
('subtype_id', 'in', conf_value),
|
||||||
|
('enabled', '=', enabled),
|
||||||
|
]).mapped('partner_id').ids
|
||||||
|
return [('id', operator, _value)]
|
||||||
|
|
||||||
|
def _search_enabled_notify_subtype_ids(self, operator, value):
|
||||||
|
return self._search_notify_subtype_ids_domain(
|
||||||
|
operator, value, True)
|
||||||
|
|
||||||
|
def _search_disabled_notify_subtype_ids(self, operator, value):
|
||||||
|
return self._search_notify_subtype_ids_domain(
|
||||||
|
operator, value, False)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _notify(self, message, force_send=False, user_signature=True):
|
||||||
|
"""Override to delegate domain generation."""
|
||||||
|
# notify_by_email
|
||||||
|
email_domain = self._get_notify_by_email_domain(message)
|
||||||
|
# `sudo` from original odoo method
|
||||||
|
# the reason should be that anybody can write messages to a partner
|
||||||
|
# and you really want to find all ppl to be notified
|
||||||
|
partners = self.sudo().search(email_domain)
|
||||||
|
partners._notify_by_email(
|
||||||
|
message, force_send=force_send, user_signature=user_signature)
|
||||||
|
# notify_by_digest
|
||||||
|
digest_domain = self._get_notify_by_email_domain(
|
||||||
|
message, digest=True)
|
||||||
|
partners = self.sudo().search(digest_domain)
|
||||||
|
partners._notify_by_digest(message)
|
||||||
|
|
||||||
|
# notify_by_chat
|
||||||
|
self._notify_by_chat(message)
|
||||||
|
return True
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _notify_by_digest(self, message):
|
||||||
|
message_sudo = message.sudo()
|
||||||
|
if not message_sudo.message_type == 'email':
|
||||||
|
return
|
||||||
|
self.env['mail.digest'].sudo().create_or_update(self, message)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_notify_by_email_domain(self, message, digest=False):
|
||||||
|
"""Return domain to collect partners to be notified by email.
|
||||||
|
|
||||||
|
:param message: instance of mail.message
|
||||||
|
:param digest: include/exclude digest enabled partners
|
||||||
|
|
||||||
|
NOTE: since mail.mail inherits from mail.message
|
||||||
|
this method is called even when
|
||||||
|
we create the final email for mail.digest object.
|
||||||
|
Here we introduce a new context flag `notify_only_recipients`
|
||||||
|
to explicitely retrieve only partners among message's recipients.
|
||||||
|
"""
|
||||||
|
|
||||||
|
message_sudo = message.sudo()
|
||||||
|
channels = message.channel_ids.filtered(
|
||||||
|
lambda channel: channel.email_send)
|
||||||
|
email = message_sudo.author_id \
|
||||||
|
and message_sudo.author_id.email or message.email_from
|
||||||
|
|
||||||
|
ids = self.ids
|
||||||
|
if self.env.context.get('notify_only_recipients'):
|
||||||
|
ids = [x for x in ids if x in message.partner_ids.ids]
|
||||||
|
domain = [
|
||||||
|
'|',
|
||||||
|
('id', 'in', ids),
|
||||||
|
('channel_ids', 'in', channels.ids),
|
||||||
|
('email', '!=', email)
|
||||||
|
]
|
||||||
|
if not digest:
|
||||||
|
domain.append(('notify_email', 'not in', ('none', 'digest')))
|
||||||
|
else:
|
||||||
|
domain.append(('notify_email', '=', 'digest'))
|
||||||
|
if message.subtype_id:
|
||||||
|
domain.extend(self._get_domain_subtype_leaf(message.subtype_id))
|
||||||
|
return domain
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_domain_subtype_leaf(self, subtype):
|
||||||
|
return [
|
||||||
|
'|',
|
||||||
|
('disabled_notify_subtype_ids', 'not in', (subtype.id, )),
|
||||||
|
('enabled_notify_subtype_ids', 'in', (subtype.id, )),
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _notify_update_subtype(self, subtype, enable):
|
||||||
|
self.ensure_one()
|
||||||
|
exists = self.env['partner.notification.conf'].search([
|
||||||
|
('subtype_id', '=', subtype.id),
|
||||||
|
('partner_id', '=', self.id)
|
||||||
|
], limit=1)
|
||||||
|
if exists:
|
||||||
|
exists.enabled = enable
|
||||||
|
else:
|
||||||
|
self.write({
|
||||||
|
'notify_conf_ids': [
|
||||||
|
(0, 0, {'enabled': enable, 'subtype_id': subtype.id})]
|
||||||
|
})
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _notify_enable_subtype(self, subtype):
|
||||||
|
self._notify_update_subtype(subtype, True)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _notify_disable_subtype(self, subtype):
|
||||||
|
self._notify_update_subtype(subtype, False)
|
||||||
|
|
||||||
|
|
||||||
|
class PartnerNotificationConf(models.Model):
|
||||||
|
"""Hold partner's single notification configuration."""
|
||||||
|
_name = 'partner.notification.conf'
|
||||||
|
_description = 'Partner notification configuration'
|
||||||
|
# TODO: add friendly onchange to not yield errors when editin via UI
|
||||||
|
_sql_constraints = [
|
||||||
|
('unique_partner_subtype_conf',
|
||||||
|
'unique (partner_id,subtype_id)',
|
||||||
|
'You can have only one configuration per subtype!')
|
||||||
|
]
|
||||||
|
|
||||||
|
partner_id = fields.Many2one(
|
||||||
|
string='Partner',
|
||||||
|
comodel_name='res.partner',
|
||||||
|
readonly=True,
|
||||||
|
required=True,
|
||||||
|
ondelete='cascade',
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
subtype_id = fields.Many2one(
|
||||||
|
'mail.message.subtype',
|
||||||
|
'Notification type',
|
||||||
|
ondelete='cascade',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
enabled = fields.Boolean(default=True, index=True)
|
|
@ -0,0 +1,5 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_mail_digest_all,mail.digest.all,model_mail_digest,,1,0,0,0
|
||||||
|
access_partner_notification_conf_all,partner.notification.all,model_partner_notification_conf,,1,0,0,0
|
||||||
|
access_mail_digest_system,mail.digest.all,model_mail_digest,base.group_system,1,1,1,1
|
||||||
|
access_partner_notification_conf_system,partner.notification.all,model_partner_notification_conf,base.group_system,1,1,1,1
|
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<template id="digest_layout" name="Mail digest layout">
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<img style="float: right" t-attf-src="data:image;base64,{{env.user.company_id.logo}}" />
|
||||||
|
<!-- if some template calling us sets this variable,
|
||||||
|
we print a h1 tag /-->
|
||||||
|
<h1 t-if="email_heading"><t t-raw="email_heading" /></h1>
|
||||||
|
<t t-raw="0" />
|
||||||
|
<!-- use some standard footer if the user doesn't have
|
||||||
|
a signature /-->
|
||||||
|
<footer t-if="not email_use_user_signature">
|
||||||
|
<p>
|
||||||
|
<a t-att-href="env.user.company_id.website">
|
||||||
|
<t t-esc="env.user.company_id.name" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p><t t-esc="env.user.company_id.phone" /></p>
|
||||||
|
</footer>
|
||||||
|
<footer t-if="email_use_user_signature">
|
||||||
|
<t t-raw="env.user.signature" />
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="default_digest_tmpl" name="Mail digest default template">
|
||||||
|
<t t-call="mail_digest.digest_layout">
|
||||||
|
<div id="mail_content">
|
||||||
|
<h2>Hello,</h2>
|
||||||
|
<div id="mail_inner_content">
|
||||||
|
<t t-foreach="grouped_messages.iterkeys()" t-as="gkey">
|
||||||
|
<t t-set="messages" t-value="grouped_messages[gkey]" />
|
||||||
|
<t t-foreach="messages" t-as="msg">
|
||||||
|
<div style="margin:20px">
|
||||||
|
<h3 t-esc="msg.subject" />
|
||||||
|
<t t-raw="msg.body" />
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</odoo>
|
|
@ -0,0 +1,3 @@
|
||||||
|
from . import test_digest
|
||||||
|
from . import test_partner_domains
|
||||||
|
from . import test_subtypes_conf
|
|
@ -0,0 +1,147 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from openerp.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class DigestCase(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(DigestCase, self).setUp()
|
||||||
|
self.partner_model = self.env['res.partner']
|
||||||
|
self.message_model = self.env['mail.message']
|
||||||
|
self.subtype_model = self.env['mail.message.subtype']
|
||||||
|
self.digest_model = self.env['mail.digest']
|
||||||
|
self.conf_model = self.env['partner.notification.conf']
|
||||||
|
|
||||||
|
self.partner1 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 1',
|
||||||
|
'email': 'partner1@test.foo.com',
|
||||||
|
})
|
||||||
|
self.partner2 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 2',
|
||||||
|
'email': 'partner2@test.foo.com',
|
||||||
|
})
|
||||||
|
self.partner3 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 3',
|
||||||
|
'email': 'partner3@test.foo.com',
|
||||||
|
})
|
||||||
|
self.subtype1 = self.subtype_model.create({'name': 'Type 1'})
|
||||||
|
self.subtype2 = self.subtype_model.create({'name': 'Type 2'})
|
||||||
|
|
||||||
|
def test_get_or_create_digest(self):
|
||||||
|
message1 = self.message_model.create({
|
||||||
|
'body': 'My Body 1',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
})
|
||||||
|
message2 = self.message_model.create({
|
||||||
|
'body': 'My Body 2',
|
||||||
|
'subtype_id': self.subtype2.id,
|
||||||
|
})
|
||||||
|
# 2 messages, 1 digest container
|
||||||
|
dig1 = self.digest_model._get_or_create_by_partner(
|
||||||
|
self.partner1, message1)
|
||||||
|
dig2 = self.digest_model._get_or_create_by_partner(
|
||||||
|
self.partner1, message2)
|
||||||
|
self.assertEqual(dig1, dig2)
|
||||||
|
|
||||||
|
def test_create_or_update_digest(self):
|
||||||
|
partners = self.partner_model
|
||||||
|
partners |= self.partner1
|
||||||
|
partners |= self.partner2
|
||||||
|
message1 = self.message_model.create({
|
||||||
|
'body': 'My Body 1',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
})
|
||||||
|
message2 = self.message_model.create({
|
||||||
|
'body': 'My Body 2',
|
||||||
|
'subtype_id': self.subtype2.id,
|
||||||
|
})
|
||||||
|
# partner 1
|
||||||
|
self.digest_model.create_or_update(self.partner1, message1)
|
||||||
|
self.digest_model.create_or_update(self.partner1, message2)
|
||||||
|
p1dig = self.digest_model._get_or_create_by_partner(self.partner1)
|
||||||
|
self.assertIn(message1, p1dig.message_ids)
|
||||||
|
self.assertIn(message2, p1dig.message_ids)
|
||||||
|
# partner 2
|
||||||
|
self.digest_model.create_or_update(self.partner2, message1)
|
||||||
|
self.digest_model.create_or_update(self.partner2, message2)
|
||||||
|
p2dig = self.digest_model._get_or_create_by_partner(self.partner2)
|
||||||
|
self.assertIn(message1, p2dig.message_ids)
|
||||||
|
self.assertIn(message2, p2dig.message_ids)
|
||||||
|
|
||||||
|
def test_notify_partner_digest(self):
|
||||||
|
message = self.message_model.create({
|
||||||
|
'body': 'My Body 1',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
})
|
||||||
|
self.partner1.notify_email = 'digest'
|
||||||
|
# notify partner
|
||||||
|
self.partner1._notify(message)
|
||||||
|
# we should find the message in its digest
|
||||||
|
dig1 = self.digest_model._get_or_create_by_partner(
|
||||||
|
self.partner1, message)
|
||||||
|
self.assertIn(message, dig1.message_ids)
|
||||||
|
|
||||||
|
def test_notify_partner_digest_followers(self):
|
||||||
|
self.partner3.message_subscribe(self.partner2.ids)
|
||||||
|
self.partner1.notify_email = 'digest'
|
||||||
|
self.partner2.notify_email = 'digest'
|
||||||
|
partners = self.partner1 + self.partner2
|
||||||
|
message = self.message_model.create({
|
||||||
|
'body': 'My Body 1',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
'res_id': self.partner3.id,
|
||||||
|
'model': 'res.partner',
|
||||||
|
'partner_ids': [(4, self.partner1.id)]
|
||||||
|
})
|
||||||
|
# notify partners
|
||||||
|
partners._notify(message)
|
||||||
|
# we should find the a digest for each partner
|
||||||
|
dig1 = self.digest_model._get_by_partner(self.partner1)
|
||||||
|
dig2 = self.digest_model._get_by_partner(self.partner2)
|
||||||
|
# and the message in them
|
||||||
|
self.assertIn(message, dig1.message_ids)
|
||||||
|
self.assertIn(message, dig2.message_ids)
|
||||||
|
# now we exclude followers
|
||||||
|
dig1.unlink()
|
||||||
|
dig2.unlink()
|
||||||
|
partners.with_context(notify_only_recipients=1)._notify(message)
|
||||||
|
# we should find the a digest for each partner
|
||||||
|
self.assertTrue(self.digest_model._get_by_partner(self.partner1))
|
||||||
|
self.assertFalse(self.digest_model._get_by_partner(self.partner2))
|
||||||
|
|
||||||
|
def _create_for_partner(self, partner):
|
||||||
|
messages = {}
|
||||||
|
for type_id in (self.subtype1.id, self.subtype2.id):
|
||||||
|
for k in xrange(1, 3):
|
||||||
|
key = '{}_{}'.format(type_id, k)
|
||||||
|
messages[key] = self.message_model.create({
|
||||||
|
'subject': 'My Subject {}'.format(key),
|
||||||
|
'body': 'My Body {}'.format(key),
|
||||||
|
'subtype_id': type_id,
|
||||||
|
})
|
||||||
|
self.digest_model.create_or_update(
|
||||||
|
partner, messages[key])
|
||||||
|
return self.digest_model._get_or_create_by_partner(partner)
|
||||||
|
|
||||||
|
def test_digest_group_messages(self):
|
||||||
|
dig = self._create_for_partner(self.partner1)
|
||||||
|
grouped = dig._message_group_by()
|
||||||
|
for type_id in (self.subtype1.id, self.subtype2.id):
|
||||||
|
self.assertIn(type_id, grouped)
|
||||||
|
self.assertEqual(len(grouped[type_id]), 2)
|
||||||
|
|
||||||
|
def test_digest_mail_values(self):
|
||||||
|
dig = self._create_for_partner(self.partner1)
|
||||||
|
values = dig._get_email_values()
|
||||||
|
expected = ('recipient_ids', 'subject', 'body_html')
|
||||||
|
for k in expected:
|
||||||
|
self.assertIn(k, values)
|
||||||
|
|
||||||
|
self.assertEqual(self.env.user.company_id.email, values['email_from'])
|
||||||
|
self.assertEqual([(4, self.partner1.id)], values['recipient_ids'])
|
|
@ -0,0 +1,169 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from openerp.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class PartnerDomainCase(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(PartnerDomainCase, self).setUp()
|
||||||
|
self.partner_model = self.env['res.partner']
|
||||||
|
self.message_model = self.env['mail.message']
|
||||||
|
self.subtype_model = self.env['mail.message.subtype']
|
||||||
|
|
||||||
|
self.partner1 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 1',
|
||||||
|
'email': 'partner1@test.foo.com',
|
||||||
|
})
|
||||||
|
self.partner2 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 2',
|
||||||
|
'email': 'partner2@test.foo.com',
|
||||||
|
})
|
||||||
|
self.partner3 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 3',
|
||||||
|
'email': 'partner3@test.foo.com',
|
||||||
|
})
|
||||||
|
self.subtype1 = self.subtype_model.create({'name': 'Type 1'})
|
||||||
|
self.subtype2 = self.subtype_model.create({'name': 'Type 2'})
|
||||||
|
|
||||||
|
def _assert_found(self, domain, not_found=False, partner=None):
|
||||||
|
partner = partner or self.partner1
|
||||||
|
if not_found:
|
||||||
|
self.assertNotIn(partner, self.partner_model.search(domain))
|
||||||
|
else:
|
||||||
|
self.assertIn(partner, self.partner_model.search(domain))
|
||||||
|
|
||||||
|
def test_notify_domains_always(self):
|
||||||
|
# we don't set recipients
|
||||||
|
# because we call `_get_notify_by_email_domain` directly
|
||||||
|
message = self.message_model.create({'body': 'My Body', })
|
||||||
|
partner = self.partner1
|
||||||
|
partner.notify_email = 'always'
|
||||||
|
domain = partner._get_notify_by_email_domain(message)
|
||||||
|
self._assert_found(domain)
|
||||||
|
domain = partner._get_notify_by_email_domain(message, digest=1)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
|
||||||
|
def test_notify_domains_only_recipients(self):
|
||||||
|
# we don't set recipients
|
||||||
|
# because we call `_get_notify_by_email_domain` directly
|
||||||
|
self.partner1.notify_email = 'always'
|
||||||
|
self.partner2.notify_email = 'always'
|
||||||
|
partners = self.partner1 + self.partner2
|
||||||
|
# followers
|
||||||
|
self.partner3.message_subscribe(self.partner2.ids)
|
||||||
|
# partner1 is the only recipient
|
||||||
|
message = self.message_model.create({
|
||||||
|
'body': 'My Body',
|
||||||
|
'res_id': self.partner3.id,
|
||||||
|
'model': 'res.partner',
|
||||||
|
'partner_ids': [(4, self.partner1.id)]
|
||||||
|
})
|
||||||
|
domain = partners._get_notify_by_email_domain(message)
|
||||||
|
# we find both of them since partner2 is a follower
|
||||||
|
self._assert_found(domain)
|
||||||
|
self._assert_found(domain, partner=self.partner2)
|
||||||
|
# no one here in digest mode
|
||||||
|
domain = partners._get_notify_by_email_domain(message, digest=1)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
self._assert_found(domain, not_found=1, partner=self.partner2)
|
||||||
|
|
||||||
|
# include only recipients
|
||||||
|
domain = partners.with_context(
|
||||||
|
notify_only_recipients=1)._get_notify_by_email_domain(message)
|
||||||
|
self._assert_found(domain)
|
||||||
|
self._assert_found(domain, partner=self.partner2, not_found=1)
|
||||||
|
|
||||||
|
def test_notify_domains_digest(self):
|
||||||
|
# we don't set recipients
|
||||||
|
# because we call `_get_notify_by_email_domain` directly
|
||||||
|
message = self.message_model.create({'body': 'My Body', })
|
||||||
|
partner = self.partner1
|
||||||
|
partner.notify_email = 'digest'
|
||||||
|
domain = partner._get_notify_by_email_domain(message)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
domain = partner._get_notify_by_email_domain(message, digest=1)
|
||||||
|
self._assert_found(domain)
|
||||||
|
|
||||||
|
def test_notify_domains_none(self):
|
||||||
|
message = self.message_model.create({'body': 'My Body', })
|
||||||
|
partner = self.partner1
|
||||||
|
partner.notify_email = 'none'
|
||||||
|
domain = partner._get_notify_by_email_domain(message)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
domain = partner._get_notify_by_email_domain(message, digest=1)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
|
||||||
|
def test_notify_domains_match_type_digest(self):
|
||||||
|
# Test message subtype matches partner settings.
|
||||||
|
# The partner can have several `partner.notification.conf` records.
|
||||||
|
# Each records establish notification rules by type.
|
||||||
|
# If you don't have any record in it, you allow all subtypes.
|
||||||
|
# Record `typeX` with `enable=True` enables notification for `typeX`.
|
||||||
|
# Record `typeX` with `enable=False` disables notification for `typeX`.
|
||||||
|
|
||||||
|
partner = self.partner1
|
||||||
|
# enable digest
|
||||||
|
partner.notify_email = 'digest'
|
||||||
|
message_t1 = self.message_model.create({
|
||||||
|
'body': 'My Body',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
})
|
||||||
|
message_t2 = self.message_model.create({
|
||||||
|
'body': 'My Body',
|
||||||
|
'subtype_id': self.subtype2.id,
|
||||||
|
})
|
||||||
|
# enable subtype on partner
|
||||||
|
partner._notify_enable_subtype(self.subtype1)
|
||||||
|
domain = partner._get_notify_by_email_domain(
|
||||||
|
message_t1, digest=True)
|
||||||
|
# notification enabled: we find the partner.
|
||||||
|
self._assert_found(domain)
|
||||||
|
# for subtype2 we don't have any explicit rule: we find the partner
|
||||||
|
domain = partner._get_notify_by_email_domain(
|
||||||
|
message_t2, digest=True)
|
||||||
|
self._assert_found(domain)
|
||||||
|
# enable subtype2: find the partner anyway
|
||||||
|
partner._notify_enable_subtype(self.subtype2)
|
||||||
|
domain = partner._get_notify_by_email_domain(
|
||||||
|
message_t2, digest=True)
|
||||||
|
self._assert_found(domain)
|
||||||
|
# disable subtype2: we don't find the partner anymore
|
||||||
|
partner._notify_disable_subtype(self.subtype2)
|
||||||
|
domain = partner._get_notify_by_email_domain(
|
||||||
|
message_t2, digest=True)
|
||||||
|
self._assert_found(domain, not_found=1)
|
||||||
|
|
||||||
|
def test_notify_domains_match_type_always(self):
|
||||||
|
message_t1 = self.message_model.create({
|
||||||
|
'body': 'My Body',
|
||||||
|
'subtype_id': self.subtype1.id,
|
||||||
|
})
|
||||||
|
message_t2 = self.message_model.create({
|
||||||
|
'body': 'My Body',
|
||||||
|
'subtype_id': self.subtype2.id,
|
||||||
|
})
|
||||||
|
# enable always
|
||||||
|
partner = self.partner1
|
||||||
|
partner.notify_email = 'always'
|
||||||
|
# enable subtype on partner
|
||||||
|
partner._notify_enable_subtype(self.subtype1)
|
||||||
|
domain = partner._get_notify_by_email_domain(message_t1)
|
||||||
|
# notification enabled: we find the partner.
|
||||||
|
self._assert_found(domain)
|
||||||
|
# for subtype2 we don't have any explicit rule: we find the partner
|
||||||
|
domain = partner._get_notify_by_email_domain(message_t2)
|
||||||
|
self._assert_found(domain)
|
||||||
|
# enable subtype2: find the partner anyway
|
||||||
|
partner._notify_enable_subtype(self.subtype2)
|
||||||
|
domain = partner._get_notify_by_email_domain(message_t2)
|
||||||
|
self._assert_found(domain)
|
||||||
|
# disable subtype2: we don't find the partner anymore
|
||||||
|
partner._notify_disable_subtype(self.subtype2)
|
||||||
|
domain = partner._get_notify_by_email_domain(message_t2)
|
||||||
|
self._assert_found(domain, not_found=1)
|
|
@ -0,0 +1,136 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Simone Orsi <simone.orsi@camptocamp.com>
|
||||||
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from openerp.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class SubtypesCase(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(SubtypesCase, self).setUp()
|
||||||
|
self.partner_model = self.env['res.partner']
|
||||||
|
self.message_model = self.env['mail.message']
|
||||||
|
self.subtype_model = self.env['mail.message.subtype']
|
||||||
|
|
||||||
|
self.partner1 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 1!',
|
||||||
|
'email': 'partner1@test.foo.com',
|
||||||
|
})
|
||||||
|
self.partner2 = self.partner_model.with_context(
|
||||||
|
tracking_disable=1).create({
|
||||||
|
'name': 'Partner 2!',
|
||||||
|
'email': 'partner2@test.foo.com',
|
||||||
|
})
|
||||||
|
self.subtype1 = self.subtype_model.create({'name': 'Type 1'})
|
||||||
|
self.subtype2 = self.subtype_model.create({'name': 'Type 2'})
|
||||||
|
|
||||||
|
def _test_subtypes_rel(self):
|
||||||
|
# setup:
|
||||||
|
# t1, t2 enabled
|
||||||
|
# t3 disabled
|
||||||
|
# t4 no conf
|
||||||
|
self.subtype3 = self.subtype_model.create({'name': 'Type 3'})
|
||||||
|
self.subtype4 = self.subtype_model.create({'name': 'Type 4'})
|
||||||
|
# enable t1 t2
|
||||||
|
self.partner1._notify_enable_subtype(self.subtype1)
|
||||||
|
self.partner1._notify_enable_subtype(self.subtype2)
|
||||||
|
# disable t3
|
||||||
|
self.partner1._notify_disable_subtype(self.subtype3)
|
||||||
|
|
||||||
|
def test_partner_computed_subtype(self):
|
||||||
|
self._test_subtypes_rel()
|
||||||
|
# check computed fields
|
||||||
|
self.assertIn(
|
||||||
|
self.subtype1, self.partner1.enabled_notify_subtype_ids)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.subtype1, self.partner1.disabled_notify_subtype_ids)
|
||||||
|
self.assertIn(
|
||||||
|
self.subtype2, self.partner1.enabled_notify_subtype_ids)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.subtype2, self.partner1.disabled_notify_subtype_ids)
|
||||||
|
self.assertIn(
|
||||||
|
self.subtype3, self.partner1.disabled_notify_subtype_ids)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.subtype3, self.partner1.enabled_notify_subtype_ids)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.subtype4,
|
||||||
|
self.partner1.enabled_notify_subtype_ids)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.subtype4,
|
||||||
|
self.partner1.disabled_notify_subtype_ids)
|
||||||
|
|
||||||
|
def test_partner_find_by_subtype_incl(self):
|
||||||
|
self._test_subtypes_rel()
|
||||||
|
domain = [(
|
||||||
|
'enabled_notify_subtype_ids',
|
||||||
|
'in', (self.subtype1.id, self.subtype2.id),
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'disabled_notify_subtype_ids', 'in', self.subtype3.id,
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'enabled_notify_subtype_ids', 'in', (self.subtype3.id, ),
|
||||||
|
)]
|
||||||
|
self.assertNotIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'enabled_notify_subtype_ids', 'in', (self.subtype4.id, ),
|
||||||
|
)]
|
||||||
|
self.assertNotIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'disabled_notify_subtype_ids', 'in', (self.subtype4.id, ),
|
||||||
|
)]
|
||||||
|
self.assertNotIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_partner_find_by_subtype_escl(self):
|
||||||
|
self._test_subtypes_rel()
|
||||||
|
domain = [(
|
||||||
|
'enabled_notify_subtype_ids',
|
||||||
|
'not in', (self.subtype4.id, ),
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'disabled_notify_subtype_ids',
|
||||||
|
'not in', (self.subtype4.id, ),
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'enabled_notify_subtype_ids',
|
||||||
|
'not in', (self.subtype3.id, ),
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
||||||
|
domain = [(
|
||||||
|
'disabled_notify_subtype_ids',
|
||||||
|
'not in', (self.subtype1.id, self.subtype2.id),
|
||||||
|
)]
|
||||||
|
self.assertIn(
|
||||||
|
self.partner1,
|
||||||
|
self.partner_model.search(domain)
|
||||||
|
)
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<openerp>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="mail_digest_tree">
|
||||||
|
<field name="name">mail_digest mail.digest.tree</field>
|
||||||
|
<field name="model">mail.digest</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Mail digest">
|
||||||
|
<field name="partner_id" />
|
||||||
|
<field name="mail_id" />
|
||||||
|
<field name="state" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="mail_digest_form">
|
||||||
|
<field name="name">mail_digest mail.digest.form</field>
|
||||||
|
<field name="model">mail.digest</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Mail digest">
|
||||||
|
<group name="main" col="4">
|
||||||
|
<field name="name" />
|
||||||
|
<field name="partner_id" />
|
||||||
|
<field name="frequency" />
|
||||||
|
<field name="mail_id" />
|
||||||
|
<field name="state" />
|
||||||
|
</group>
|
||||||
|
<group name="messages" string="Messages" col="4">
|
||||||
|
<field name="message_ids" nolabel="1" />
|
||||||
|
</group>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.actions.act_window" id="action_digest_all">
|
||||||
|
<field name="name">Digest</field>
|
||||||
|
<field name="res_model">mail.digest</field>
|
||||||
|
<field name="view_type">form</field>
|
||||||
|
<field name="view_mode">form,tree</field>
|
||||||
|
<field name="view_id" ref="mail_digest_tree" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_email_digest" parent="base.menu_email"
|
||||||
|
action="action_digest_all"
|
||||||
|
sequence="90"/>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</openerp>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<openerp>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="notifications_emails_partner_info_form" model="ir.ui.view">
|
||||||
|
<field name="name">mail.notifications res.partner.form</field>
|
||||||
|
<field name="model">res.partner</field>
|
||||||
|
<field name="inherit_id" ref="mail.view_emails_partner_info_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='notify_email']" position="after">
|
||||||
|
<field name="notify_conf_ids" attrs="{'invisible': [('notify_email','=', 'none')]}"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="notification_form">
|
||||||
|
<field name="name">partner.notification.conf form</field>
|
||||||
|
<field name="model">partner.notification.conf</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Notification">
|
||||||
|
<group name="main">
|
||||||
|
<field name="enabled" />
|
||||||
|
<field name="subtype_id" options="{'no_create': True}" />
|
||||||
|
</group>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="notification_tree">
|
||||||
|
<field name="name">partner.notification.conf tree</field>
|
||||||
|
<field name="model">partner.notification.conf</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Notifications" editable="top">
|
||||||
|
<field name="enabled" />
|
||||||
|
<field name="subtype_id" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</openerp>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<openerp>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="notifications_email_user_info_form" model="ir.ui.view">
|
||||||
|
<field name="name">mail.notifications res.users.form</field>
|
||||||
|
<field name="model">res.users</field>
|
||||||
|
<field name="inherit_id" ref="mail.view_users_form_mail"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='notify_email']" position="after">
|
||||||
|
<field name="notify_frequency" attrs="{'invisible': [('notify_email','=', 'none')]}" />
|
||||||
|
<field name="notify_conf_ids" attrs="{'invisible': [('notify_email','=', 'none')]}" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</openerp>
|
Loading…
Reference in New Issue