[REF] mail: refactored system to generate links in signatures. A new server action...
authorThibault Delavallée <tde@openerp.com>
Wed, 17 Apr 2013 12:22:25 +0000 (14:22 +0200)
committerThibault Delavallée <tde@openerp.com>
Wed, 17 Apr 2013 12:22:25 +0000 (14:22 +0200)
bzr revid: tde@openerp.com-20130417122225-faf0bb5vyhbcx7ys

addons/mail/mail_mail.py
addons/mail/mail_message_view.xml
addons/mail/mail_thread.py
addons/mail/mail_thread_view.xml
addons/mail/static/src/js/mail.js
addons/mail/tests/test_mail_gateway.py
addons/portal/__init__.py
addons/portal/mail_mail.py

index 351ff01..089cabf 100644 (file)
@@ -28,7 +28,6 @@ from urlparse import urljoin
 from openerp import tools
 from openerp import SUPERUSER_ID
 from openerp.osv import fields, osv
-from openerp.osv.orm import except_orm
 from openerp.tools.translate import _
 
 _logger = logging.getLogger(__name__)
@@ -150,6 +149,31 @@ class mail_mail(osv.Model):
             self.unlink(cr, SUPERUSER_ID, [mail.id], context=context)
         return True
 
+    #------------------------------------------------------
+    # mail_mail formatting, tools and send mechanism
+    #------------------------------------------------------
+
+    def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None):
+        """ Generate URLs for links in mails:
+            - partner is an user and has read access to the document: direct link to document with model, res_id
+        """
+        if partner and partner.user_ids:
+            base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
+            # the parameters to encode for the query and fragment part of url
+            query = {'db': cr.dbname}
+            fragment = {
+                'login': partner.user_ids[0].login,
+                'action': 'mail.action_mail_redirect',
+            }
+            if mail.notification:
+                fragment.update({
+                        'message_id': mail.mail_message_id.id,
+                    })
+            url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment)))
+            return _("""<small>Access this document <a style='color:inherit' href="%s">directly in OpenERP</a></small>""") % url
+        else:
+            return None
+
     def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None):
         """ If subject is void and record_name defined: '<Author> posted on <Resource>'
 
@@ -170,25 +194,10 @@ class mail_mail(osv.Model):
             :param browse_record partner: specific recipient partner
         """
         body = mail.body_html
-        # partner is a user, link to a related document (incentive to install portal)
-        if partner and partner.user_ids and mail.model and mail.res_id \
-                and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False):
-            related_user = partner.user_ids[0]
-            try:
-                self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context)
-                base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
-                # the parameters to encode for the query and fragment part of url
-                query = {'db': cr.dbname}
-                fragment = {
-                    'login': related_user.login,
-                    'model': mail.model,
-                    'id': mail.res_id,
-                }
-                url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment)))
-                text = _("""<p>Access this document <a href="%s">directly in OpenERP</a></p>""") % url
-                body = tools.append_content_to_html(body, ("<div><p>%s</p></div>" % text), plaintext=False)
-            except except_orm, e:
-                pass
+        # generate footer
+        link = self._get_partner_access_link(cr, uid, mail, partner, context=context)
+        if link:
+            body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div')
         return body
 
     def send_get_mail_reply_to(self, cr, uid, mail, partner=None, context=None):
index 8f2fb3f..02f4ef7 100644 (file)
@@ -59,6 +59,9 @@
                     <field name="type"/>
                     <field name="author_id"/>
                     <field name="partner_ids"/>
+                    <field name="model"/>
+                    <field name="res_id"/>
+                    <field name="parent_id"/>
                     <filter string="To Read"
                             name="message_unread" help="Show messages to read"
                             domain="[('to_read', '=', True)]"/>
index 23341ac..08cf1f1 100644 (file)
@@ -389,6 +389,54 @@ class mail_thread(osv.AbstractModel):
             return [('message_unread', '=', True)]
         return []
 
+    def message_redirect_get_inbox_action_xml_id(self, cr, uid, context=None):
+        """ When redirecting towards the Inbox, choose which action xml_id has
+            to be fetched. This method is meant to be inherited, at least in portal
+            because portal users have a different Inbox action than classic users. """
+        return ('mail', 'action_mail_inbox_feeds')
+
+    def message_redirect_action(self, cr, uid, context=None):
+        """ For a given message, return an action that either
+            - opens the form view of the related document if model, res_id, and
+              read access to the document
+            - opens the Inbox with a default search on the conversation if model,
+              res_id
+            - opens the Inbox with context propagated
+        """
+        if context is None:
+            context = {}
+
+        # default action is the Inbox action
+        self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
+        act_model, act_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, *self.message_redirect_get_inbox_action_xml_id(cr, uid, context=context))
+        action = self.pool.get(act_model).read(cr, uid, act_id, [])
+
+        # if msg_id specified: try to redirect to the document or fallback on the Inbox
+        msg_id = context.get('params', {}).get('message_id')
+        if not msg_id:
+            return action
+        msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
+        if msg.model and msg.res_id and self.pool.get(msg.model).check_access_rights(cr, uid, 'read', raise_exception=False):
+            try:
+                self.pool.get(msg.model).check_access_rule(cr, uid, [msg.res_id], 'read', context=context)
+                action = {
+                    'type': 'ir.actions.act_window',
+                    'res_model': msg.model,
+                    'view_type': 'form',
+                    'view_mode': 'form',
+                    'views': [(msg.res_id, 'form')],
+                    'target': 'current',
+                    'res_id': msg.res_id,
+                }
+            except osv.except_osv:
+                action.update({
+                    'context': {
+                        'search_default_model': msg.model,
+                        'search_default_res_id': msg.res_id,
+                    }
+                })
+        return action
+
     #------------------------------------------------------
     # Email specific
     #------------------------------------------------------
@@ -1078,36 +1126,6 @@ class mail_thread(osv.AbstractModel):
             self.message_subscribe(cr, uid, [thread_id], [message.author_id.id], context=context)
         return msg_id
 
-    def get_message_action_from_link(self, cr, uid, message_id, context=None):
-        action = None
-        msg_obj = self.pool.get('mail.message')
-        msg = msg_obj.browse(cr, uid, message_id, context=context)
-        if msg.model:
-            try:
-                self.pool.get(msg.model).check_access_rights(cr, uid, 'read')
-                action = {
-                    'type': 'ir.actions.act_window',
-                    'res_model': msg.model,
-                    'view_type': 'form',
-                    'view_mode': 'form',
-                    'views': [(msg.res_id, 'form')],
-                    'target': 'current',
-                    'res_id': msg.res_id,
-                }
-            except openerp.exceptions.AccessDenied:
-                mod_obj = self.pool.get('ir.model.data')
-                act_model, act_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'action_mail_inbox_feeds')
-                action = self.pool.get(act_model).read(cr, uid, act_id, [])
-                action.update({
-                    'context': {
-                        'default_model': 'res.users',
-                        'default_res_id': uid,
-                        'search_default_res_id': 1,
-                        'search_default_model': 1,
-                    }
-                })
-        return action
-
     #------------------------------------------------------
     # Compatibility methods: do not use
     # TDE TODO: remove me in 8.0
index 62fde0c..6c7bdc2 100644 (file)
@@ -8,8 +8,6 @@
             <field name="context">{
               'default_model': 'res.users',
               'default_res_id': uid,
-              'search_default_model': context.get('params') and context.params.get('model'),
-              'search_default_res_id': context.get('params') and context.params.get('res_id')
             }</field>
             <field name="params" eval="&quot;{
                 'domain': [
             </field>
         </record>
 
+        <record id="action_mail_redirect" model="ir.actions.server">
+            <field name="name">Mail Redirection (Document / Inbox)</field>
+            <field name="condition">True</field>
+            <field name="model_id" ref="model_mail_thread"/>
+            <field name="code">action = pool.get('mail.thread').message_redirect_action(cr, uid, context)</field>
+            <field name="state">code</field>
+            <field name="type">ir.actions.server</field>
+        </record>
+
         <!-- MENU -->
 
         <!-- Top menu item -->
index f3306b4..580cca9 100644 (file)
@@ -1834,10 +1834,19 @@ openerp.mail = function (session) {
             this._super(parent, action);
 
             this.action = _.clone(action);
+            // debugger
             this.domain = this.action.params.domain || this.action.domain || [];
             this.context = _.extend(this.action.params.context || {}, this.action.context || {});
 
+            // filter some parameters that we will propagate as search_default
             this.defaults = {};
+            for (var key in this.action.context.params) {
+                if (_.indexOf(['model', 'res_id'], key) == -1) {
+                    continue;
+                }
+                this.context['search_default_' + key] = this.action.context.params[key];
+                console.log(this.context);
+            }
             for (var key in this.context) {
                 if (key.match(/^search_default_/)) {
                     this.defaults[key.replace(/^search_default_/, '')] = this.context[key];
@@ -1995,5 +2004,4 @@ openerp.mail = function (session) {
             });
         },
     });
-
 };
index a680112..738945e 100644 (file)
@@ -20,6 +20,7 @@
 ##############################################################################
 
 from openerp.addons.mail.tests.test_mail_base import TestMailBase
+from openerp.tools import mute_logger
 
 MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
 To: {to}
@@ -83,6 +84,7 @@ Sylvie
 
 class TestMailgateway(TestMailBase):
 
+    @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
     def test_00_message_process(self):
         """ Testing incoming emails processing. """
         cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
@@ -325,6 +327,7 @@ class TestMailgateway(TestMailBase):
         self.assertEqual(msg.body, '<pre>\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n</pre>',
                             'message_process: plaintext incoming email incorrectly parsed')
 
+    @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
     def test_10_thread_parent_resolution(self):
         """ Testing parent/child relationships are correctly established when processing incoming mails """
         cr, uid = self.cr, self.uid
index 0045a55..3a9b5ef 100644 (file)
@@ -20,6 +20,7 @@
 ##############################################################################
 
 import portal
+import mail_thread
 import mail_mail
 import wizard
 import acquirer
index 5d2a91e..3565845 100644 (file)
@@ -21,8 +21,6 @@
 
 from openerp import SUPERUSER_ID
 from openerp.osv import osv
-from openerp.osv.orm import except_orm
-from openerp.tools import append_content_to_html
 from openerp.tools.translate import _
 
 
@@ -30,27 +28,18 @@ class mail_mail(osv.Model):
     """ Update of mail_mail class, to add the signin URL to notifications. """
     _inherit = 'mail.mail'
 
-    def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
-        """ add a signin link inside the body of a mail.mail
-            :param mail: mail.mail browse_record
-            :param partner: browse_record of the specific recipient partner
-            :return: the resulting body_html
+    def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None):
+        """ Generate URLs for links in mails:
+            - partner is not an user: signup_url
+            - partner is an user: fallback on classic URL
         """
-        partner_obj = self.pool.get('res.partner')
-        body = mail.body_html
-        if partner:
+        if partner and not partner.user_ids:
             contex_signup = dict(context or {}, signup_valid=True)
-            partner = partner_obj.browse(cr, SUPERUSER_ID, partner.id, context=contex_signup)
-            text = _("""<p>Access your messages and personal documents through <a href="%s">our Customer Portal</a></p>""") % partner.signup_url
-            # partner is an user: add a link to the document if read access
-            if partner.user_ids and mail.model and mail.res_id \
-                    and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False):
-                related_user = partner.user_ids[0]
-                try:
-                    self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context)
-                    url = partner_obj._get_signup_url_for_action(cr, related_user.id, [partner.id], action='', res_id=mail.res_id, model=mail.model, context=context)[partner.id]
-                    text = _("""<p>Access this document <a href="%s">directly in OpenERP</a></p>""") % url
-                except except_orm, e:
-                    pass
-            body = append_content_to_html(body, ("<div><p>%s</p></div>" % text), plaintext=False)
-        return body
+            partner = self.pool.get('res.partner').browse(cr, SUPERUSER_ID, partner.id, context=contex_signup)
+            return _("""<small>Access your messages and documents through <a style='color:inherit' href="%s">our Customer Portal</a></small>""") % partner.signup_url
+        else:
+            return super(mail_mail, self)._get_partner_access_link(cr, uid, mail, partner=partner, context=context)
+
+    def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
+        """ TODO: remove me in 8.0 """
+        return super(mail_mail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context)