Browse Source

Merge pull request #256 from CompassionCH/10.0-mig-mail_forward

[10.0][MIG] migrate module mail_forward
pull/240/head
Pedro M. Baeza 6 years ago
committed by GitHub
parent
commit
15d2e407c6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 101
      mail_forward/README.rst
  2. 5
      mail_forward/__init__.py
  3. 27
      mail_forward/__manifest__.py
  4. 168
      mail_forward/i18n/es.po
  5. 5
      mail_forward/models/__init__.py
  6. 99
      mail_forward/models/compose_message.py
  7. 14
      mail_forward/models/res_request_link.py
  8. BIN
      mail_forward/static/description/icon.png
  9. 24
      mail_forward/static/src/css/mail_forward.less
  10. 123
      mail_forward/static/src/js/mail_forward.js
  11. 12
      mail_forward/static/src/xml/mail_forward.xml
  12. 5
      mail_forward/tests/__init__.py
  13. 57
      mail_forward/tests/test_compose_message.py
  14. 17
      mail_forward/views/assets.xml
  15. 55
      mail_forward/views/compose_message.xml
  16. 30
      mail_forward/views/res_request_link.xml

101
mail_forward/README.rst

@ -0,0 +1,101 @@
.. 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
===============
Message forward
===============
This module was written to extend the functionality of mails to support
forwarding them to another contact or database object.
* **To another object of the database:** All its followers are notified
according to their settings.
* **To other contacts:** They recieve the forwarded message according to the
usual notification rules of Odoo.
Configuration
=============
When installed, this module allows forwarding to a limited selection of
database models, that will get automatically updated when you install other
modules.
This list can be customized by a user that has *Technical Features* permission.
To do it:
* Go to *Settings > Technical > Database Structure > Referenceable Models*.
* Any model there with *Mail forward target* enabled will appear in the list of
models that can get forwarded messages.
* If you want to *remove* a model from the list, it's usually better to just
*disable* its check box instead of deleting it, because that record might
be used by other modules.
Usage
=====
To use this module, you need to:
* Go to any view that has a message thread.
* Press *Forward* (the button with a curved arrow pointing to the right).
* Modify the subject if you wish.
* If you want to forward the message to an *object*, choose it from the
selector.
* If you want to forward the message to some partner(s), add them in the
selector.
* Modify the message if you want.
* Add attachments if you want.
* If the message contains attachments, you can turn on the *Move attachments*
option, and those will get attached to the new object.
You will need to install the *document* module and have at least *User*
permissions for *Knowledge* to see the effect.
.. info::
Technical note: Internally, forwarded messages are modified copies of
original ones, but attachments are references to the exact originals to
avoid duplicating disk space. Keep that in mind when managing permissions.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/8.0
For further information, please visit:
* https://www.odoo.com/forum/help-1
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
------------
* Jairo Llopis <jairo.llopis@tecnativa.com>
* Emanuel Cino <ecino@compassion.ch>
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 http://odoo-community.org.

5
mail_forward/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

27
mail_forward/__manifest__.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Message Forward",
"summary": "Add option to forward messages",
"version": "10.0.1.0.0",
"category": "Social Network",
"website": "https://github.com/OCA/social",
"author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"mail",
"web",
],
"data": [
"views/assets.xml",
"views/compose_message.xml",
"views/res_request_link.xml",
],
"qweb": [
"static/src/xml/mail_forward.xml",
],
}

168
mail_forward/i18n/es.po

@ -0,0 +1,168 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mail_forward
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-02 09:15+0000\n"
"PO-Revision-Date: 2015-11-02 10:19+0100\n"
"Last-Translator: Jairo Llopis <j.llopis@grupoesoc.es>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"Language: es\n"
"X-Generator: Poedit 1.8.5\n"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:25
#, python-format
msgid "(No subject)"
msgstr "(Sin asunto)"
#. module: mail_forward
#: help:res.request.link,mail_forward_target:0
msgid "Allow to forward mails to this model."
msgstr "Permitir reenviar correos a este modelo."
#. module: mail_forward
#: help:mail_forward.compose_message,move_attachments:0
msgid "Attachments will be assigned to the chosen destination object and you will be able to pick them from its 'Attachments' button, but they will not be there for the current object if any. In any case you can always open it from the message itself."
msgstr "Los adjuntos se asignarán al objeto de destino escogido y podrá escogerlos desde el botón 'Adjuntos', pero desaparecerán del objeto en el que estén actualmente (si están en alguno). En cualquier caso, siempre podrá abrirlos desde el propio mensaje."
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:47
#, python-format
msgid "CC: "
msgstr "CC: "
#. module: mail_forward
#: field:mail_forward.compose_message,create_uid:0
msgid "Created by"
msgstr "Creado por"
#. module: mail_forward
#: field:mail_forward.compose_message,create_date:0
msgid "Created on"
msgstr "Creado el"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:38
#, python-format
msgid "Date: "
msgstr "Fecha: "
#. module: mail_forward
#: field:mail_forward.compose_message,destination_object_id:0
msgid "Destination object"
msgstr "Objeto de destino"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:16
#, python-format
msgid "FWD"
msgstr "RV"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/xml/mail_forward.xml:10
#, python-format
msgid "Forward"
msgstr "Reenviar"
#. module: mail_forward
#: model:ir.actions.act_window,name:mail_forward.compose_action
msgid "Forward Email"
msgstr "Reenviar correo electrónico"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:36
#, python-format
msgid "Forwarded message"
msgstr "Mensaje reenviado"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:37
#, python-format
msgid "From: "
msgstr "De: "
#. module: mail_forward
#: field:mail_forward.compose_message,id:0
msgid "ID"
msgstr "ID"
#. module: mail_forward
#: field:mail_forward.compose_message,write_uid:0
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: mail_forward
#: field:mail_forward.compose_message,write_date:0
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: mail_forward
#: field:res.request.link,mail_forward_target:0
msgid "Mail forward target"
msgstr "Objetivo al reenviar"
#. module: mail_forward
#: field:mail_forward.compose_message,move_attachments:0
msgid "Move attachments"
msgstr "Mover adjuntos"
#. module: mail_forward
#: help:mail_forward.compose_message,destination_object_id:0
msgid "Object where the forwarded message will be attached"
msgstr "Objeto al que se añadirá el mensaje reenviado"
#. module: mail_forward
#: field:mail_forward.compose_message,original_wizard_id:0
msgid "Original message compose wizard"
msgstr "Asistente original de composición de mensajes"
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:41
#, python-format
msgid "Subject: "
msgstr "Asunto: "
#. module: mail_forward
#. openerp-web
#: code:addons/mail_forward/static/src/js/mail_forward.js:44
#, python-format
msgid "To: "
msgstr "Para: "
#. module: mail_forward
#: view:mail_forward.compose_message:mail_forward.compose_form
msgid ""
"{\n"
" 'invisible': [('destination_object_id', '=', False)]\n"
" }"
msgstr ""
"{\n"
" 'invisible': [('destination_object_id', '=', False)]\n"
" }"
#. module: mail_forward
#: view:mail_forward.compose_message:mail_forward.compose_form
msgid ""
"{\n"
" 'required': [('destination_object_id', '=', False)]\n"
" }"
msgstr ""
"{\n"
" 'required': [('destination_object_id', '=', False)]\n"
" }"

5
mail_forward/models/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import compose_message, res_request_link

99
mail_forward/models/compose_message.py

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
class MailForwardComposeMessage(models.TransientModel):
"""Allow forwarding a message.
It duplicates the message and optionally attaches it to another object
of the database and sends it to another recipients than the original one.
"""
_name = "mail_forward.compose_message"
_inherits = {"mail.compose.message": "original_wizard_id"}
@api.model
def default_get(self, fields):
"""Fix default values.
Sometimes :meth:`openerp.addons.mail.mail_compose_message
.mail_compose_message.default_get` overwrites the default value
for the ``subject`` field, even when it gets the right default value
from the context.
This method fixes that by getting it from the context if available.
"""
result = self.original_wizard_id.default_get(fields)
if "subject" in result and "default_subject" in self.env.context:
result["subject"] = self.env.context["default_subject"]
return result
@api.model
def _get_model_selection(self):
"""Get allowed models and their names."""
model_objs = self.env["res.request.link"].search(
[("mail_forward_target", "=", True)],
order="name")
return [(m.object, m.name) for m in model_objs]
@api.onchange("destination_object_id")
def change_destination_object(self):
"""Update some fields for the new message."""
if self.destination_object_id:
self.model = self.destination_object_id._name
self.res_id = self.destination_object_id.id
model_name = (self.env["ir.model"]
.search([("model", "=", self.model)])
.name)
record_name = self.destination_object_id.name_get()[0][1]
if model_name:
record_name = "%s %s" % (model_name, record_name)
self.record_name = record_name
@api.multi
def send_mail_action(self):
# action buttons call with positional arguments only, so we need an
# intermediary function to ensure the context is passed correctly
return self.send_mail()
def send_mail(self):
"""Send mail and execute the attachment relocation if needed."""
# Let the original wizard do de hard work
result = self.original_wizard_id.send_mail()
# Relocate attachments if needed
if (self.move_attachments and
self.model and
self.res_id and
self.attachment_ids):
for attachment in self.attachment_ids:
attachment.res_model = self.model
attachment.res_id = self.res_id
return result
destination_object_id = fields.Reference(
_get_model_selection,
"Destination object",
help="Object where the forwarded message will be attached")
move_attachments = fields.Boolean(
"Move attachments",
help="Attachments will be assigned to the chosen destination "
"object and you will be able to pick them from its "
"'Attachments' button, but they will not be there for "
"the current object if any. In any case you can always "
"open it from the message itself.")
original_wizard_id = fields.Many2one(
"mail.compose.message",
"Original message compose wizard",
delegate=True,
ondelete="cascade",
required=True)

14
mail_forward/models/res_request_link.py

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class ResRequestLink(models.Model):
_inherit = "res.request.link"
mail_forward_target = fields.Boolean(
default=True,
index=True,
help="Allow to forward mails to this model.")

BIN
mail_forward/static/description/icon.png

After

Width: 100  |  Height: 100  |  Size: 1.8 KiB

24
mail_forward/static/src/css/mail_forward.less

@ -0,0 +1,24 @@
/* (C) 2018 CompassionCH <www.compassion.ch>
/* (C) 2014-2015 Grupo ESOC <www.grupoesoc.es>
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
*/
@mail-thread-icon-opacity: 0.6;
.o_mail_thread {
.o_thread_message {
i.o_forward {
cursor: pointer;
opacity: 0;
}
&:hover, &.o_thread_selected_message {
i.o_forward {
opacity: @mail-thread-icon-opacity;
&:hover {
opacity: 1;
}
}
}
}
}

123
mail_forward/static/src/js/mail_forward.js

@ -0,0 +1,123 @@
/* © 2014-2015 Grupo ESOC <www.grupoesoc.es>
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
*/
odoo.define('mail_forward.forward', function (require) {
"use strict";
var core = require('web.core');
var ChatThread = require('mail.ChatThread');
var chat_manager = require('mail.chat_manager');
var Model = require('web.Model');
var session = require('web.session');
var MessageModel = new Model('mail.message', session.user_context);
var _t = core._t;
ChatThread.include({
on_message_forward: function (message_id) {
var self = this;
var read_fields = ['record_name', 'parent_id', 'subject', 'attachment_ids', 'date',
'email_to', 'email_from', 'email_cc', 'model', 'res_id', 'body'];
// Generate email subject as possible from record_name and subject
MessageModel.call('read', [message_id, read_fields], {context: session.user_context}).then(function (result) {
var message = result[0];
var subject = [_t("FWD")];
if (message.record_name && message.parent_id) {
subject.push(message.record_name);
}
if (message.subject) {
subject.push(message.subject);
} else if (subject.length < 2) {
subject.push(_t("(No subject)"));
}
// Get only ID from the attachments
var attachment_ids = [];
for (var n in message.attachment_ids) {
attachment_ids.push(message.attachment_ids[n]);
}
// Get necessary fields from the forwarded message
var header = [
"----------" + _t("Forwarded message") + "----------",
_t("From: ") + message.email_from,
_t("Date: ") + message.date
];
if (message.subject) {
header.push(_t("Subject: ") + message.subject);
}
if (message.email_to) {
header.push(_t("To: ") + message.email_to);
}
if (message.email_cc) {
header.push(_t("CC: ") + message.email_cc);
}
header = header.map(_.str.escapeHTML).join("<br/>");
var context = {
default_attachment_ids: attachment_ids,
default_body:
"<p><i>" + header + "</i></p><br/>" +
message.body,
default_model: message.model,
default_res_id: message.res_id,
default_subject: subject.join(": ")
};
if (message.model && message.res_id) {
context.default_destination_object_id =
[message.model, message.res_id].join();
}
// Get the action data and execute it to open the composer wizard
var do_action = self.do_action;
self.rpc("/web/action/load", {
"action_id": "mail_forward.compose_action"
})
.done(function (action) {
action.context = context;
do_action(action, {
on_close: $.proxy(self.thread_reload, self)
});
});
});
},
init: function (parent, options) {
this._super.apply(this, arguments);
// Add click reaction in the events of the thread object
this.events['click .o_forward'] = function (event) {
var message_id = $(event.currentTarget).data('message-id');
this.trigger("message_forward", message_id);
};
},
thread_reload: function(){
var parent = this.getParent();
var domain = [['model', '=', parent.model], ['res_id', '=', parent.res_id]];
var self = this;
MessageModel.call('message_fetch', [domain], {limit: 30}).then(function (msgs) {
var messages = _.map(msgs, chat_manager.make_message);
// Avoid displaying in reverse order
self.options.display_order = 1;
self.render(messages, self.options)
});
}
});
var chatter = require('mail.Chatter');
chatter.include({
start: function () {
var result = this._super.apply(this, arguments);
this.thread.on('message_forward', this, this.thread.on_message_forward);
return result;
}
});
var ChatAction = core.action_registry.get('mail.chat.instant_messaging');
ChatAction.include({
start: function () {
var result = this._super.apply(this, arguments);
// For show wizard in the channels
this.thread.on('message_forward', this, this.thread.on_message_forward);
return result;
}
});
});

12
mail_forward/static/src/xml/mail_forward.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- © 2014-2015 Grupo ESOC <www.grupoesoc.es>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<template>
<t t-extend="mail.ChatThread.Message">
<t t-jquery=".o_thread_message_reply" t-operation="after">
<i class="fa fa-share o_forward" title="Forward" t-att-data-message-id="message.id"/>
</t>
</t>
</template>

5
mail_forward/tests/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_compose_message

57
mail_forward/tests/test_compose_message.py

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# © 2014-2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from os import path
from odoo.tests.common import TransactionCase
class ForwardMailCase(TransactionCase):
def setUp(self, *args, **kwargs):
super(ForwardMailCase, self).setUp(*args, **kwargs)
self.compose = self.env["mail.compose.message"].create({})
self.fwd = self.env["mail_forward.compose_message"].create({
"original_wizard_id": self.compose.id,
})
self.partner = self.env["res.partner"].create({"name": __file__})
self.attachment = self.env["ir.attachment"].create({
"name": "Testing source",
"datas_fname": path.basename(__file__),
"type": "url",
"url": "file://%s" % __file__,
})
def test_subject(self):
"""Test correct subject is used."""
self.compose.subject = "Bad subject"
good = "Good subject"
defaults = self.fwd.with_context(default_subject=good).default_get(
["subject"])
self.assertEqual(defaults["subject"], good)
def test_change_destination(self):
"""Test what happens when changing the destination."""
model = self.env["ir.model"].search(
[("model", "=", self.partner._name)])
# Set a partner as destination object
self.fwd.destination_object_id = self.partner
self.fwd.change_destination_object()
self.assertEqual(self.fwd.model, self.partner._name)
self.assertEqual(self.fwd.res_id, self.partner.id)
self.assertEqual(self.fwd.record_name,
"%s %s" % (model.name, self.partner.name))
def test_move_attachments(self):
"""Attachments moved correctly."""
self.fwd.attachment_ids |= self.attachment
self.fwd.destination_object_id = self.partner
self.fwd.change_destination_object()
self.fwd.body = "body"
self.fwd.subject = "subject"
self.fwd.move_attachments = True
self.fwd.send_mail()
self.assertEqual(self.attachment.res_model, self.partner._name)
self.assertEqual(self.attachment.res_id, self.partner.id)

17
mail_forward/views/assets.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2014-2015 Grupo ESOC <www.grupoesoc.es>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<template id="assets_backend"
name="Mail forward assets"
inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/mail_forward/static/src/css/mail_forward.less" type="text/less"/>
<script type="text/javascript" src="/mail_forward/static/src/js/mail_forward.js"/>
</xpath>
</template>
</odoo>

55
mail_forward/views/compose_message.xml

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2014-2015 Grupo ESOC <www.grupoesoc.es>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<record id="compose_form" model="ir.ui.view">
<field name="name">Forward Email Form</field>
<field name="model">mail_forward.compose_message</field>
<field name="inherit_id" ref="mail.email_compose_message_wizard_form"/>
<field name="arch" type="xml">
<data>
<!-- It's required to fill either `partner_ids` or
`destination_object_id` -->
<xpath expr="//field[@name='partner_ids']" position="attributes">
<attribute name="attrs">{
'required': [('destination_object_id', '=', False)]
}
</attribute>
</xpath>
<xpath expr="//label[@for='partner_ids']" position="before">
<!-- Object where the message will be attached -->
<field
attrs="{
'required': [('partner_ids', '=', [[6, False, []]])]}"
name="destination_object_id"/>
<!-- If the message has attachments, should we move them to the
new object? -->
<field
name="move_attachments"
attrs="{
'invisible': [
'|',
('destination_object_id', '=', False),
('attachment_ids', '=', [[6, False, []]])]}"/>
</xpath>
</data>
</field>
</record>
<record id="compose_action" model="ir.actions.act_window">
<field name="name">Forward Email</field>
<field name="res_model">mail_forward.compose_message</field>
<field name="src_model">mail.message</field>
<field name="type">ir.actions.act_window</field>
<field name="view_id" ref="compose_form"/>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>

30
mail_forward/views/res_request_link.xml

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2014-2015 Grupo ESOC <www.grupoesoc.es>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<record id="res_request_link_view_form" model="ir.ui.view">
<field name="name">Add option to forward mails</field>
<field name="model">res.request.link</field>
<field name="inherit_id" ref="base.res_request_link-view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='priority']" position="after">
<field name="mail_forward_target"/>
</xpath>
</field>
</record>
<record id="res_request_link_view_tree" model="ir.ui.view">
<field name="name">Add option to forward mails</field>
<field name="model">res.request.link</field>
<field name="inherit_id" ref="base.res_request_link_tree-view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='object']" position="after">
<field name="mail_forward_target"/>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save