[MIG] mail_tracking: Migration to 11.0

pull/318/head
David 2018-03-19 16:41:26 +01:00 committed by ernesto
parent 9365804a27
commit 0fd2b031ef
24 changed files with 122 additions and 168 deletions

View File

@ -10,7 +10,6 @@ This module shows email notification tracking status for any messages in
mail thread (chatter). Each notified partner will have an intuitive icon just mail thread (chatter). Each notified partner will have an intuitive icon just
right to his name. right to his name.
Installation Installation
============ ============
@ -20,7 +19,6 @@ you need to add ``mail_tracking`` addon to wide load addons list
(by default, only ``web`` addon), setting ``--load`` option. (by default, only ``web`` addon), setting ``--load`` option.
For example, ``--load=web,mail_tracking`` For example, ``--load=web,mail_tracking``
Usage Usage
===== =====
@ -63,7 +61,7 @@ These are all available status icons:
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot :alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/10.0 :target: https://runbot.odoo-community.org/runbot/205/11.0
If you want to see all tracking emails and events you can go to If you want to see all tracking emails and events you can go to
@ -93,8 +91,11 @@ Images
Contributors Contributors
------------ ------------
* Pedro M. Baeza <pedro.baeza@tecnativa.com> * `Tecnativa <https://www.tecnativa.com>`_:
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* David Vidal <david.vidal@tecnativa.com>
Maintainer Maintainer
---------- ----------

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import models from . import models
from . import controllers from . import controllers

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> # Copyright 2018 David Vidal - <david.vidal@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{ {
"name": "Email tracking", "name": "Email tracking",
"summary": "Email tracking system for all mails sent", "summary": "Email tracking system for all mails sent",
"version": "10.0.1.1.1", "version": "11.0.1.0.0",
"category": "Social Network", "category": "Social Network",
"website": "http://www.tecnativa.com", "website": "http://github.com/OCA/social",
"author": "Tecnativa, " "author": "Tecnativa, "
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",
"license": "AGPL-3", "license": "AGPL-3",

View File

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import main from . import main

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import werkzeug import werkzeug
@ -8,7 +7,7 @@ from odoo import api, http, registry, SUPERUSER_ID
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
BLANK = 'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' BLANK = b'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
def _env_get(db, callback, tracking_id, event_type, **kw): def _env_get(db, callback, tracking_id, event_type, **kw):
@ -22,7 +21,7 @@ def _env_get(db, callback, tracking_id, event_type, **kw):
reg = registry(db) reg = registry(db)
except OperationalError: except OperationalError:
_logger.warning("Selected BD '%s' not found", db) _logger.warning("Selected BD '%s' not found", db)
except: # pragma: no cover except Exception: # pragma: no cover
_logger.warning("Selected BD '%s' connection error", db) _logger.warning("Selected BD '%s' connection error", db)
if reg: if reg:
_logger.info("New environment for database '%s'", db) _logger.info("New environment for database '%s'", db)
@ -83,5 +82,5 @@ class MailTrackingController(http.Controller):
# Always return GIF blank image # Always return GIF blank image
response = werkzeug.wrappers.Response() response = werkzeug.wrappers.Response()
response.mimetype = 'image/gif' response.mimetype = 'image/gif'
response.data = BLANK.decode('base64') response.data = BLANK
return response return response

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>
<record forcecreate="True" id="decimal_tracking_timestamp" model="decimal.precision"> <record forcecreate="True" id="decimal_tracking_timestamp" model="decimal.precision">

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging import logging

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import ir_mail_server from . import ir_mail_server
from . import mail_mail from . import mail_mail

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re import re
@ -20,16 +19,10 @@ class IrMailServer(models.Model):
def _tracking_email_id_body_get(self, body): def _tracking_email_id_body_get(self, body):
body = body or '' body = body or ''
tracking_email_id = False
# https://regex101.com/r/lW4cB1/2 # https://regex101.com/r/lW4cB1/2
match = re.search( match = re.search(
r'<img[^>]*data-odoo-tracking-email=["\']([0-9]*)["\']', body) r'<img[^>]*data-odoo-tracking-email=["\']([0-9]*)["\']', body)
if match: return int(match.group(1)) if match.group(1) else False
try:
tracking_email_id = int(match.group(1))
except: # pragma: no cover
pass
return tracking_email_id
def build_email(self, email_from, email_to, subject, body, email_cc=None, def build_email(self, email_from, email_to, subject, body, email_cc=None,
email_bcc=None, reply_to=False, attachments=None, email_bcc=None, reply_to=False, attachments=None,
@ -64,14 +57,14 @@ class IrMailServer(models.Model):
mail_server = mail_server_ids[0] if mail_server_ids else None mail_server = mail_server_ids[0] if mail_server_ids else None
if mail_server: if mail_server:
smtp_server_used = mail_server.smtp_host smtp_server_used = mail_server.smtp_host
else: # pragma: no cover else:
smtp_server_used = smtp_server or tools.config.get('smtp_server') smtp_server_used = smtp_server or tools.config.get('smtp_server')
return smtp_server_used return smtp_server_used
@api.model @api.model
def send_email(self, message, mail_server_id=None, smtp_server=None, def send_email(self, message, mail_server_id=None, smtp_server=None,
smtp_port=None, smtp_user=None, smtp_password=None, smtp_port=None, smtp_user=None, smtp_password=None,
smtp_encryption=None, smtp_debug=False): smtp_encryption=None, smtp_debug=False, smtp_session=None):
message_id = False message_id = False
tracking_email = self._tracking_email_get(message) tracking_email = self._tracking_email_get(message)
smtp_server_used = self.sudo()._smtp_server_get( smtp_server_used = self.sudo()._smtp_server_get(
@ -82,7 +75,8 @@ class IrMailServer(models.Model):
message, mail_server_id=mail_server_id, message, mail_server_id=mail_server_id,
smtp_server=smtp_server, smtp_port=smtp_port, smtp_server=smtp_server, smtp_port=smtp_port,
smtp_user=smtp_user, smtp_password=smtp_password, smtp_user=smtp_user, smtp_password=smtp_password,
smtp_encryption=smtp_encryption, smtp_debug=smtp_debug) smtp_encryption=smtp_encryption, smtp_debug=smtp_debug,
smtp_session=smtp_session)
except Exception as e: except Exception as e:
if tracking_email: if tracking_email:
tracking_email.smtp_error(self, smtp_server_used, e) tracking_email.smtp_error(self, smtp_server_used, e)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time import time

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, api from odoo import models, api

View File

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging import logging
import urlparse import urllib.parse
import time import time
import re import re
from datetime import datetime from datetime import datetime
@ -93,27 +92,20 @@ class MailTrackingEmail(models.Model):
string="Tracking events", comodel_name='mail.tracking.event', string="Tracking events", comodel_name='mail.tracking.event',
inverse_name='tracking_email_id', readonly=True) inverse_name='tracking_email_id', readonly=True)
@api.model
def _email_score_tracking_filter(self, domain, order='time desc',
limit=10):
"""Default tracking search. Ready to be inherited."""
return self.search(domain, limit=limit, order=order)
@api.model @api.model
def email_is_bounced(self, email): def email_is_bounced(self, email):
if email: if email:
return len(self._email_score_tracking_filter([ return self.search_count([
('recipient_address', '=', email.lower()), ('recipient_address', '=', email.lower()),
('state', 'in', ('error', 'rejected', 'spam', 'bounced')), ('state', 'in', ('error', 'rejected', 'spam', 'bounced')),
])) > 0 ]) > 0
return False return False
@api.model @api.model
def email_score_from_email(self, email): def email_score_from_email(self, email):
if email: if email:
return self._email_score_tracking_filter([ return self.search([
('recipient_address', '=', email.lower()) ('recipient_address', '=', email.lower())]).email_score()
]).email_score()
return 0. return 0.
@api.model @api.model
@ -183,7 +175,7 @@ class MailTrackingEmail(models.Model):
'db': self.env.cr.dbname, 'db': self.env.cr.dbname,
'tracking_email_id': self.id, 'tracking_email_id': self.id,
}) })
track_url = urlparse.urljoin(base_url, path_url) track_url = urllib.parse.urljoin(base_url, path_url)
return ( return (
'<img src="%(url)s" alt="" ' '<img src="%(url)s" alt="" '
'data-odoo-tracking-email="%(tracking_email_id)s"/>' % { 'data-odoo-tracking-email="%(tracking_email_id)s"/>' % {
@ -197,7 +189,7 @@ class MailTrackingEmail(models.Model):
if event and event.recipient_address: if event and event.recipient_address:
recipients.append(event.recipient_address) recipients.append(event.recipient_address)
else: else:
recipients = list(filter(None, self.mapped('recipient_address'))) recipients = [x for x in self.mapped('recipient_address') if x]
for recipient in recipients: for recipient in recipients:
self.env['res.partner'].search([ self.env['res.partner'].search([
('email', '=ilike', recipient) ('email', '=ilike', recipient)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re import re

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, api, fields from odoo import models, api, fields

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>

View File

@ -1,4 +1,4 @@
/* © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> /* Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
.mail_tracking span { .mail_tracking span {

View File

@ -1,98 +1,83 @@
/* © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> /* Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
Copyright 2018 David Vidal - <david.vidal@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
odoo.define('mail_tracking.partner_tracking', function(require){ odoo.define('mail_tracking.partner_tracking', function(require){
"use strict"; "use strict";
var core = require('web.core'); var core = require('web.core');
var session = require('web.session'); var session = require('web.session');
var Model = require('web.Model'); var data = require('web.data');
var ActionManager = require('web.ActionManager'); var ActionManager = require('web.ActionManager');
var ChatThread = require('mail.ChatThread'); var chat_manager = require('mail.chat_manager');
var ChatThread = require('mail.ChatThread');
var Chatter = require('mail.Chatter');
var _t = core._t; var _t = core._t;
var MessageModel = new Model('mail.message', session.context);
// chat_manager is a simple dictionary, not an OdooClass
ChatThread.include({ chat_manager._make_message_super = chat_manager.make_message;
_preprocess_message: function (message) { chat_manager.make_message = function(data) {
var msg = this._super.apply(this, arguments); var msg = this._make_message_super(data);
msg.partner_trackings = msg.partner_trackings || []; msg.partner_trackings = data.partner_trackings || [];
return msg; return msg;
}, };
on_tracking_partner_click: function (event) {
var partner_id = this.$el.find(event.currentTarget).data('partner'); ChatThread.include({
var state = { events: _.extend(ChatThread.prototype.events, {
'model': 'res.partner', 'click .o_mail_action_tracking_partner': 'on_tracking_partner_click',
'id': partner_id, 'click .o_mail_action_tracking_status': 'on_tracking_status_click',
'title': _t("Tracking partner"), }),
}; _preprocess_message: function (message) {
event.preventDefault(); var msg = this._super.apply(this, arguments);
this.action_manager.do_push_state(state); msg.partner_trackings = msg.partner_trackings || [];
var action = { return msg;
type:'ir.actions.act_window', },
view_type: 'form', on_tracking_partner_click: function (event) {
view_mode: 'form', var partner_id = this.$el.find(event.currentTarget).data('partner');
res_model: 'res.partner', var state = {
views: [[false, 'form']], 'model': 'res.partner',
target: 'current', 'id': partner_id,
res_id: partner_id, 'title': _t("Tracking partner"),
}; };
this.do_action(action); event.preventDefault();
}, this.action_manager.do_push_state(state);
on_tracking_status_click: function (event) { var action = {
var tracking_email_id = $(event.currentTarget).data('tracking'); type:'ir.actions.act_window',
var state = { view_type: 'form',
'model': 'mail.tracking.email', view_mode: 'form',
'id': tracking_email_id, res_model: 'res.partner',
'title': _t("Message tracking"), views: [[false, 'form']],
}; target: 'current',
event.preventDefault(); res_id: partner_id,
this.action_manager.do_push_state(state); };
var action = { this.do_action(action);
type:'ir.actions.act_window', },
view_type: 'form', on_tracking_status_click: function (event) {
view_mode: 'form', var tracking_email_id = $(event.currentTarget).data('tracking');
res_model: 'mail.tracking.email', var state = {
views: [[false, 'form']], 'model': 'mail.tracking.email',
target: 'new', 'id': tracking_email_id,
res_id: tracking_email_id, 'title': _t("Message tracking"),
}; };
this.do_action(action); event.preventDefault();
}, this.action_manager.do_push_state(state);
bind_events: function () { var action = {
this.$el.on('click', '.o_mail_action_tracking_partner', type:'ir.actions.act_window',
this.on_tracking_partner_click); view_type: 'form',
this.$el.on('click', '.o_mail_action_tracking_status', view_mode: 'form',
this.on_tracking_status_click); res_model: 'mail.tracking.email',
}, views: [[false, 'form']],
init: function (parent, options) { target: 'new',
this._super.apply(this, arguments); res_id: tracking_email_id,
this.action_manager = this.findAncestor(function(ancestor){ };
return ancestor instanceof ActionManager; this.do_action(action);
}); },
}, init: function (parent, options) {
start: function () { this._super.apply(this, arguments);
this._super(); this.action_manager = this.findAncestor(function(ancestor){
this.bind_events(); return ancestor instanceof ActionManager;
},
render: function(messages, options) {
var self = this, render_super = this._super,
msgs = {},
msg_ids = [];
// Update trackings (async) each time we re-render thread
_.each(messages, function (message) {
msgs[message.id] = message;
msg_ids.push(message.id);
});
MessageModel.call('tracking_status', [msg_ids]).then(function (trackings) {
_.each(trackings, function (tracking, id) {
msgs[id].partner_trackings = tracking;
}); });
render_super.apply(self, [messages, options]); },
}); });
},
}); });
}); // odoo.define

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<template> <template>
@ -47,7 +47,7 @@
<t t-set="first_tracking" t-value="true"/> <t t-set="first_tracking" t-value="true"/>
<t t-foreach="message.partner_trackings" t-as="tracking"> <t t-foreach="message.partner_trackings" t-as="tracking">
<t t-if="!first_tracking"> <t t-if="!first_tracking">
- -
</t> </t>
<t t-if="tracking[3]"> <t t-if="tracking[3]">
<a class="o_mail_action_tracking_partner" <a class="o_mail_action_tracking_partner"

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa # flake8: noqa

View File

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> # Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import mock import mock
from odoo.tools import mute_logger from odoo.tools import mute_logger
import base64
import time import time
from odoo import http from odoo import http
from odoo.tests.common import TransactionCase from odoo.tests.common import TransactionCase
@ -29,12 +28,10 @@ class TestMailTracking(TransactionCase):
self.sender = self.env['res.partner'].create({ self.sender = self.env['res.partner'].create({
'name': 'Test sender', 'name': 'Test sender',
'email': 'sender@example.com', 'email': 'sender@example.com',
'notify_email': 'always',
}) })
self.recipient = self.env['res.partner'].create({ self.recipient = self.env['res.partner'].create({
'name': 'Test recipient', 'name': 'Test recipient',
'email': 'recipient@example.com', 'email': 'recipient@example.com',
'notify_email': 'always',
}) })
self.last_request = http.request self.last_request = http.request
http.request = type('obj', (object,), { http.request = type('obj', (object,), {
@ -138,7 +135,7 @@ class TestMailTracking(TransactionCase):
def test_mail_send(self): def test_mail_send(self):
controller = MailTrackingController() controller = MailTrackingController()
db = self.env.cr.dbname db = self.env.cr.dbname
image = base64.decodestring(BLANK) image = BLANK
mail, tracking = self.mail_send(self.recipient.email) mail, tracking = self.mail_send(self.recipient.email)
self.assertEqual(mail.email_to, tracking.recipient) self.assertEqual(mail.email_to, tracking.recipient)
self.assertEqual(mail.email_from, tracking.sender) self.assertEqual(mail.email_from, tracking.sender)
@ -310,8 +307,8 @@ class TestMailTracking(TransactionCase):
db = self.env.cr.dbname db = self.env.cr.dbname
controller = MailTrackingController() controller = MailTrackingController()
not_found = controller.mail_tracking_all('not_found_db') not_found = controller.mail_tracking_all('not_found_db')
self.assertEqual('NOT FOUND', not_found.response[0]) self.assertEqual(b'NOT FOUND', not_found.response[0])
none = controller.mail_tracking_all(db) none = controller.mail_tracking_all(db)
self.assertEqual('NONE', none.response[0]) self.assertEqual(b'NONE', none.response[0])
none = controller.mail_tracking_event(db, 'open') none = controller.mail_tracking_event(db, 'open')
self.assertEqual('NONE', none.response[0]) self.assertEqual(b'NONE', none.response[0])

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>
<template id="assets_backend" <template id="assets_backend"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> <!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>