[FIX] stock: fixed views for stock.quant
[odoo/odoo.git] / addons / mail / mail_followers.py
index 1824a7b..0059df9 100644 (file)
@@ -20,6 +20,8 @@
 ##############################################################################
 from openerp.osv import osv, fields
 from openerp import tools, SUPERUSER_ID
+from openerp.tools.translate import _
+from openerp.tools.mail import plaintext2html
 
 class mail_followers(osv.Model):
     """ mail_followers holds the data related to the follow mechanism inside
@@ -61,39 +63,39 @@ class mail_notification(osv.Model):
         'read': fields.boolean('Read', select=1),
         'starred': fields.boolean('Starred', select=1,
             help='Starred message that goes into the todo mailbox'),
-        'date': fields.date('Date'),
         'message_id': fields.many2one('mail.message', string='Message',
                         ondelete='cascade', required=True, select=1),
     }
 
     _defaults = {
         'read': False,
-        'date': lambda *a: fields.datetime.now(),
         'starred': False,
     }
 
     def init(self, cr):
-        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_starred_date_message_id',))
+        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_starred_message_id',))
         if not cr.fetchone():
-            cr.execute('CREATE INDEX mail_notification_partner_id_read_starred_date_message_id ON mail_notification (partner_id, read, starred, date, message_id)')
+            cr.execute('CREATE INDEX mail_notification_partner_id_read_starred_message_id ON mail_notification (partner_id, read, starred, message_id)')
 
-    def get_partners_to_notify(self, cr, uid, message, context=None):
+    def get_partners_to_email(self, cr, uid, ids, message, context=None):
         """ Return the list of partners to notify, based on their preferences.
 
             :param browse_record message: mail.message to notify
+            :param list partners_to_notify: optional list of partner ids restricting
+                the notifications to process
         """
         notify_pids = []
-        for notification in message.notification_ids:
+        for notification in self.browse(cr, uid, ids, context=context):
             if notification.read:
                 continue
             partner = notification.partner_id
-            # Do not send an email to the writer
-            if partner.user_ids and partner.user_ids[0].id == uid:
-                continue
             # Do not send to partners without email address defined
             if not partner.email:
                 continue
-            # Partner does not want to receive any emails
+            # Do not send to partners having same email address than the author (can cause loops or bounce effect due to messy database)
+            if message.author_id and message.author_id.email == partner.email:
+                continue
+            # Partner does not want to receive any emails or is opt-out
             if partner.notification_email_send == 'none':
                 continue
             # Partner wants to receive only emails and comments
@@ -105,43 +107,114 @@ class mail_notification(osv.Model):
             notify_pids.append(partner.id)
         return notify_pids
 
-    def _notify(self, cr, uid, msg_id, context=None):
-        """ Send by email the notification depending on the user preferences """
-        if context is None:
-            context = {}
-        # mail_notify_noemail (do not send email) or no partner_ids: do not send, return
-        if context.get('mail_notify_noemail'):
-            return True
-        # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed
-        msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context)
-        notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context)
-        if not notify_partner_ids:
+    def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None):
+        """ Format a standard footer for notification emails (such as pushed messages
+            notification or invite emails).
+            Format:
+                <p>--<br />
+                    Administrator
+                </p>
+                <div>
+                    <small>Sent by <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> OR
+                    <small>Sent by Administrator using <a ...>OpenERP</a>.</small>
+                </div>
+        """
+        footer = ""
+        if not user_id:
+            return footer
+
+        # add user signature
+        user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0]
+        if user.signature:
+            signature = plaintext2html(user.signature)
+        else:
+            signature = "--<br />%s" % user.name
+        footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p')
+
+        # add company signature
+        if user.company_id.website:
+            website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \
+                else user.company_id.website
+            company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name)
+        else:
+            company = user.company_id.name
+        sent_by = _('Sent by %(company)s using %(openerp)s.')
+        signature_company = '<small>%s</small>' % (sent_by % {
+            'company': company,
+            'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>"
+        })
+        footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div')
+
+        return footer
+
+    def update_message_notification(self, cr, uid, ids, message_id, partner_ids, context=None):
+        existing_pids = set()
+        new_pids = set()
+        new_notif_ids = []
+
+        for notification in self.browse(cr, uid, ids, context=context):
+            existing_pids.add(notification.partner_id.id)
+
+        # update existing notifications
+        self.write(cr, uid, ids, {'read': False}, context=context)
+
+        # create new notifications
+        new_pids = set(partner_ids) - existing_pids
+        for new_pid in new_pids:
+            new_notif_ids.append(self.create(cr, uid, {'message_id': message_id, 'partner_id': new_pid, 'read': False}, context=context))
+        return new_notif_ids
+
+    def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None):
+        message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context)
+
+        # compute partners
+        email_pids = self.get_partners_to_email(cr, uid, ids, message, context=None)
+        if not email_pids:
             return True
 
-        # add the context in the email
-        # TDE FIXME: commented, to be improved in a future branch
-        # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context)
+        # compute email body (signature, company data)
+        body_html = message.body
+        user_id = message.author_id and message.author_id.user_ids and message.author_id.user_ids[0] and message.author_id.user_ids[0].id or None
+        if user_signature:
+            signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context)
+            body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
 
-        mail_mail = self.pool.get('mail.mail')
-        # add signature
-        body_html = msg.body
-        # if quote_context:
-            # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
-        signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
-        if signature:
-            body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
+        # compute email references
+        references = message.parent_id.message_id if message.parent_id else False
 
+        # create email values
         mail_values = {
-            'mail_message_id': msg.id,
-            'email_to': [],
+            'mail_message_id': message.id,
             'auto_delete': True,
             'body_html': body_html,
-            'state': 'outgoing',
+            'recipient_ids': [(4, id) for id in email_pids],
+            'references': references,
         }
-        mail_values['email_to'] = ', '.join(mail_values['email_to'])
-        email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
-        try:
-            return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context)
-        except Exception:
-            return False
+        email_notif_id = self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)
+        if force_send:
+            self.pool.get('mail.mail').send(cr, uid, [email_notif_id], context=context)
+        return True
+
+    def _notify(self, cr, uid, message_id, partners_to_notify=None, context=None,
+                force_send=False, user_signature=True):
+        """ Send by email the notification depending on the user preferences
+
+            :param list partners_to_notify: optional list of partner ids restricting
+                the notifications to process
+            :param bool force_send: if True, the generated mail.mail is
+                immediately sent after being created, as if the scheduler
+                was executed for this message only.
+            :param bool user_signature: if True, the generated mail.mail body is
+                the body of the related mail.message with the author's signature
+        """
+        notif_ids = self.search(cr, SUPERUSER_ID, [('message_id', '=', message_id), ('partner_id', 'in', partners_to_notify)], context=context)
 
+        # update or create notifications
+        new_notif_ids = self.update_message_notification(cr, SUPERUSER_ID, notif_ids, message_id, partners_to_notify, context=context)
+
+        # mail_notify_noemail (do not send email) or no partner_ids: do not send, return
+        if context and context.get('mail_notify_noemail'):
+            return True
+
+        # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed
+        self._notify_email(cr, SUPERUSER_ID, new_notif_ids, message_id, force_send, user_signature, context=context)