mirror of https://github.com/OCA/social.git
[MIG][mass_mailing_custom_unsubscribe] Migrate to v10
parent
d6f874d1e2
commit
1af75e7684
|
@ -10,7 +10,7 @@ This addon extends the unsubscription form to let you:
|
||||||
|
|
||||||
- Choose which mailing lists are not cross-unsubscriptable when unsubscribing
|
- Choose which mailing lists are not cross-unsubscriptable when unsubscribing
|
||||||
from a different one.
|
from a different one.
|
||||||
- Know why and when a contact as been unsubscribed from a mass mailing.
|
- Know why and when a contact has been unsubscribed from a mass mailing.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
=============
|
=============
|
||||||
|
@ -21,7 +21,7 @@ Unsubscription Reasons
|
||||||
You can customize what reasons will be displayed to your unsubscriptors when
|
You can customize what reasons will be displayed to your unsubscriptors when
|
||||||
they are going to unsubscribe. To do it:
|
they are going to unsubscribe. To do it:
|
||||||
|
|
||||||
#. Go to *Marketing > Configuration > Unsubscription Reasons*.
|
#. Go to *Mass Mailing > Configuration > Unsubscription Reasons*.
|
||||||
#. Create / edit / remove / sort as usual.
|
#. Create / edit / remove / sort as usual.
|
||||||
#. If *Details required* is enabled, they will have to fill a text area to
|
#. If *Details required* is enabled, they will have to fill a text area to
|
||||||
continue.
|
continue.
|
||||||
|
@ -40,7 +40,7 @@ Once configured:
|
||||||
|
|
||||||
.. 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/9.0
|
:target: https://runbot.odoo-community.org/runbot/205/10.0
|
||||||
|
|
||||||
Known issues / Roadmap
|
Known issues / Roadmap
|
||||||
======================
|
======================
|
||||||
|
@ -48,7 +48,9 @@ Known issues / Roadmap
|
||||||
* This module adds a security hash for mass mailing unsubscription URLs, which
|
* This module adds a security hash for mass mailing unsubscription URLs, which
|
||||||
disables insecure URLs from mass mailing messages sent before its
|
disables insecure URLs from mass mailing messages sent before its
|
||||||
installation. This can be a problem, but anyway you'd get that problem in
|
installation. This can be a problem, but anyway you'd get that problem in
|
||||||
Odoo 11.0, so at least this addon will be forward-compatible with it.
|
Odoo 11.0, where https://github.com/odoo/odoo/pull/12040 was merged, so at
|
||||||
|
least this addon will be forward-compatible with it. So, **this feature must
|
||||||
|
be removed from here when migrating to v11**.
|
||||||
* This module replaces AJAX submission core implementation from the mailing
|
* This module replaces AJAX submission core implementation from the mailing
|
||||||
list management form, because it is impossible to extend it. When
|
list management form, because it is impossible to extend it. When
|
||||||
https://github.com/odoo/odoo/pull/14386 gets merged (which upstreams most
|
https://github.com/odoo/odoo/pull/14386 gets merged (which upstreams most
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
'name': "Customizable unsubscription process on mass mailing emails",
|
'name': "Customizable unsubscription process on mass mailing emails",
|
||||||
"summary": "Know unsubscription reasons, track them",
|
"summary": "Know unsubscription reasons, track them",
|
||||||
'category': 'Marketing',
|
'category': 'Marketing',
|
||||||
'version': '9.0.2.0.0',
|
'version': '10.0.1.0.0',
|
||||||
'depends': [
|
'depends': [
|
||||||
'website_mass_mailing',
|
'website_mass_mailing',
|
||||||
],
|
],
|
||||||
|
@ -25,8 +25,7 @@
|
||||||
'images': [
|
'images': [
|
||||||
'images/form.png',
|
'images/form.png',
|
||||||
],
|
],
|
||||||
'author': 'Antiun Ingeniería S.L., '
|
'author': 'Tecnativa,'
|
||||||
'Tecnativa,'
|
|
||||||
'Odoo Community Association (OCA)',
|
'Odoo Community Association (OCA)',
|
||||||
'website': 'https://www.tecnativa.com',
|
'website': 'https://www.tecnativa.com',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
|
|
|
@ -29,7 +29,7 @@ class CustomUnsubscribe(MassMailController):
|
||||||
Security token for unsubscriptions.
|
Security token for unsubscriptions.
|
||||||
"""
|
"""
|
||||||
reasons = request.env["mail.unsubscription.reason"].search([])
|
reasons = request.env["mail.unsubscription.reason"].search([])
|
||||||
return request.website.render(
|
return request.render(
|
||||||
"mass_mailing_custom_unsubscribe.reason_form",
|
"mass_mailing_custom_unsubscribe.reason_form",
|
||||||
{
|
{
|
||||||
"email": email,
|
"email": email,
|
||||||
|
@ -75,11 +75,11 @@ class CustomUnsubscribe(MassMailController):
|
||||||
return self.reason_form(mailing, email, res_id, token)
|
return self.reason_form(mailing, email, res_id, token)
|
||||||
else:
|
else:
|
||||||
# Unsubscribe, saving reason and details by context
|
# Unsubscribe, saving reason and details by context
|
||||||
request.context.update({
|
request.context = dict(
|
||||||
"default_reason_id": reason_id,
|
request.context,
|
||||||
"default_details": post.get("details") or False,
|
default_reason_id=reason_id,
|
||||||
})
|
default_details=post.get("details") or False,
|
||||||
del request.env
|
)
|
||||||
# You could get a DetailsRequiredError here, but only if HTML5
|
# You could get a DetailsRequiredError here, but only if HTML5
|
||||||
# validation fails, which should not happen in modern browsers
|
# validation fails, which should not happen in modern browsers
|
||||||
return super(CustomUnsubscribe, self).mailing(
|
return super(CustomUnsubscribe, self).mailing(
|
||||||
|
@ -91,8 +91,11 @@ class CustomUnsubscribe(MassMailController):
|
||||||
"""Store unsubscription reasons when unsubscribing from RPC."""
|
"""Store unsubscription reasons when unsubscribing from RPC."""
|
||||||
# Update request context and reset environment
|
# Update request context and reset environment
|
||||||
if reason_id:
|
if reason_id:
|
||||||
request.context["default_reason_id"] = int(reason_id)
|
request.context = dict(
|
||||||
request.context["default_details"] = details or False
|
request.context,
|
||||||
|
default_reason_id=int(reason_id),
|
||||||
|
default_details=details or False,
|
||||||
|
)
|
||||||
# FIXME Remove token check in version where this is merged:
|
# FIXME Remove token check in version where this is merged:
|
||||||
# https://github.com/odoo/odoo/pull/14385
|
# https://github.com/odoo/odoo/pull/14385
|
||||||
mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
|
mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
|
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from openerp import api, models
|
from openerp import models
|
||||||
|
|
||||||
|
|
||||||
class MailMail(models.Model):
|
class MailMail(models.Model):
|
||||||
_inherit = 'mail.mail'
|
_inherit = 'mail.mail'
|
||||||
|
|
||||||
@api.model
|
def _get_unsubscribe_url(self, email_to):
|
||||||
def _get_unsubscribe_url(self, mail, email_to):
|
result = super(MailMail, self)._get_unsubscribe_url(email_to)
|
||||||
result = super(MailMail, self)._get_unsubscribe_url(mail, email_to)
|
token = self.mailing_id._unsubscribe_token(self.res_id)
|
||||||
token = mail.mailing_id._unsubscribe_token(mail.res_id)
|
|
||||||
return "%s&token=%s" % (result, token)
|
return "%s&token=%s" % (result, token)
|
||||||
|
|
|
@ -37,18 +37,17 @@ class MailMassMailing(models.Model):
|
||||||
raise AccessDenied()
|
raise AccessDenied()
|
||||||
return token
|
return token
|
||||||
|
|
||||||
@api.model
|
def update_opt_out(self, email, res_ids, value):
|
||||||
def update_opt_out(self, mailing_id, email, res_ids, value):
|
|
||||||
"""Save unsubscription reason when opting out from mailing."""
|
"""Save unsubscription reason when opting out from mailing."""
|
||||||
mailing = self.browse(mailing_id)
|
self.ensure_one()
|
||||||
if value and self.env.context.get("default_reason_id"):
|
if value and self.env.context.get("default_reason_id"):
|
||||||
for res_id in res_ids:
|
for res_id in res_ids:
|
||||||
# reason_id and details are expected from the context
|
# reason_id and details are expected from the context
|
||||||
self.env["mail.unsubscription"].create({
|
self.env["mail.unsubscription"].create({
|
||||||
"email": email,
|
"email": email,
|
||||||
"mass_mailing_id": mailing.id,
|
"mass_mailing_id": self.id,
|
||||||
"unsubscriber_id": "%s,%d" % (
|
"unsubscriber_id": "%s,%d" % (
|
||||||
mailing.mailing_model, int(res_id)),
|
self.mailing_model, int(res_id)),
|
||||||
})
|
})
|
||||||
return super(MailMassMailing, self).update_opt_out(
|
return super(MailMassMailing, self).update_opt_out(
|
||||||
mailing_id, email, res_ids, value)
|
email, res_ids, value)
|
||||||
|
|
|
@ -3,4 +3,4 @@ read_unsubscription_reason_public,Public users can read unsubscription reasons,m
|
||||||
read_unsubscription_reason_employee,Employee users can read unsubscription reasons,model_mail_unsubscription_reason,base.group_user,1,0,0,0
|
read_unsubscription_reason_employee,Employee users can read unsubscription reasons,model_mail_unsubscription_reason,base.group_user,1,0,0,0
|
||||||
write_unsubscription_reason,Mass mailing managers can manage unsubscription reasons,model_mail_unsubscription_reason,mass_mailing.group_mass_mailing_user,1,1,1,1
|
write_unsubscription_reason,Mass mailing managers can manage unsubscription reasons,model_mail_unsubscription_reason,mass_mailing.group_mass_mailing_user,1,1,1,1
|
||||||
read_unsubscription,Marketing users can read unsubscriptions,model_mail_unsubscription,mass_mailing.group_mass_mailing_user,1,0,0,0
|
read_unsubscription,Marketing users can read unsubscriptions,model_mail_unsubscription,mass_mailing.group_mass_mailing_user,1,0,0,0
|
||||||
write_unsubscription,Mass mailing managers can manage unsubscriptions,model_mail_unsubscription,mass_mailing.group_mass_mailing_user,1,1,1,1
|
write_unsubscription,Admins can change unsubscriptions,model_mail_unsubscription,base.group_system,1,1,1,1
|
||||||
|
|
|
|
@ -3,75 +3,72 @@
|
||||||
odoo.define("mass_mailing_custom_unsubscribe.contact_tour",
|
odoo.define("mass_mailing_custom_unsubscribe.contact_tour",
|
||||||
function (require) {
|
function (require) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var Tour = require("web.Tour");
|
var base = require("web_editor.base");
|
||||||
|
var tour = require("web_tour.tour");
|
||||||
require("mass_mailing_custom_unsubscribe.require_details");
|
require("mass_mailing_custom_unsubscribe.require_details");
|
||||||
require("mass_mailing_custom_unsubscribe.unsubscribe");
|
require("mass_mailing_custom_unsubscribe.unsubscribe");
|
||||||
|
|
||||||
// Allow to know if an element is required
|
// Allow to know if an element is required
|
||||||
$.extend($.expr[':'], {
|
$.extend($.expr[':'], {
|
||||||
propRequired: function(element, index, matches) {
|
propRequired: function(element, index, matches) {
|
||||||
return $(element).prop("required");
|
return $(element).prop("required");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Tour.register({
|
tour.register(
|
||||||
id: "mass_mailing_custom_unsubscribe_tour_contact",
|
"mass_mailing_custom_unsubscribe_tour_contact",
|
||||||
name: "Mass mailing contact unsubscribes",
|
{
|
||||||
mode: "test",
|
tour: true,
|
||||||
steps: [
|
wait_for: base.ready(),
|
||||||
|
},
|
||||||
|
[
|
||||||
{
|
{
|
||||||
title: "Unsubscription reasons are invisible",
|
content: "Unsubscription reasons are invisible",
|
||||||
waitFor: "#unsubscribe_form .js_unsubscription_reason:hidden",
|
trigger: "#unsubscribe_form:has(.js_unsubscription_reason:hidden)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Uncheck list 0",
|
content: "Uncheck list 0",
|
||||||
element: "li:contains('test list 0') input",
|
trigger: "li:contains('test list 0') input",
|
||||||
waitFor: "li:contains('test list 0') input:checked",
|
|
||||||
// List 2 is not cross unsubscriptable
|
// List 2 is not cross unsubscriptable
|
||||||
waitNot: "li:contains('test list 2')",
|
extra_trigger: "body:not(:has(li:contains('test list 2'))) li:contains('test list 0') input:checked",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Uncheck list 1",
|
content: "Uncheck list 1",
|
||||||
element: "li:contains('test list 1') input:checked",
|
trigger: "li:contains('test list 1') input:checked",
|
||||||
waitFor: ".js_unsubscription_reason:visible",
|
extra_trigger: ".js_unsubscription_reason:visible",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Choose other reason",
|
content: "Choose other reason",
|
||||||
element: ".radio:contains('Other reason') :radio",
|
trigger: ".radio:contains('Other reason') :radio",
|
||||||
waitFor: ".radio:contains('Other reason') " +
|
extra_trigger: ".radio:contains('Other reason') " +
|
||||||
":radio:not(:checked)",
|
":radio:not(:checked)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Add details to reason",
|
content: "Add details to reason",
|
||||||
element: "[name='details']:visible:propRequired",
|
trigger: "[name='details']:visible:propRequired",
|
||||||
sampleText: "I want to unsubscribe because I want. Period.",
|
run: "text I want to unsubscribe because I want. Period.",
|
||||||
waitFor: ".radio:contains('Other reason') :radio:checked",
|
extra_trigger: ".radio:contains('Other reason') :radio:checked",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Update subscriptions 1st time",
|
content: "Update subscriptions 1st time",
|
||||||
element: "#unsubscribe_form :submit",
|
trigger: "#unsubscribe_form :submit",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Subscribe again to list 0",
|
content: "Subscribe again to list 0",
|
||||||
element: "li:contains('test list 0') input:not(:checked)",
|
trigger: "body:not(:has(#unsubscribe_form .js_unsubscription_reason:visible)):has(.alert-success, li:contains('test list 0') input:not(:checked))",
|
||||||
waitFor: ".alert-success",
|
run: function () {
|
||||||
waitNot: "#unsubscribe_form .js_unsubscription_reason:visible",
|
|
||||||
onend: function () {
|
|
||||||
// This one will get the success again after next step
|
// This one will get the success again after next step
|
||||||
$(".alert-success").removeClass("alert-success");
|
$(".alert-success").removeClass("alert-success");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Update subscriptions 2nd time",
|
content: "Update subscriptions 2nd time",
|
||||||
element: "#unsubscribe_form :submit",
|
trigger: "#unsubscribe_form:not(:has(.js_unsubscription_reason:visible)) :submit",
|
||||||
waitNot: "#unsubscribe_form .js_unsubscription_reason:visible",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Resuscription was OK",
|
content: "Resuscription was OK",
|
||||||
waitFor: ".alert-success",
|
trigger: ".alert-success",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
);
|
||||||
|
|
||||||
return Tour.tours.mass_mailing_custom_unsubscribe_tour_contact;
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,47 +3,44 @@
|
||||||
odoo.define("mass_mailing_custom_unsubscribe.partner_tour",
|
odoo.define("mass_mailing_custom_unsubscribe.partner_tour",
|
||||||
function (require) {
|
function (require) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var Tour = require("web.Tour");
|
var base = require("web_editor.base");
|
||||||
|
var tour = require("web_tour.tour");
|
||||||
require("mass_mailing_custom_unsubscribe.require_details");
|
require("mass_mailing_custom_unsubscribe.require_details");
|
||||||
require("mass_mailing_custom_unsubscribe.unsubscribe");
|
require("mass_mailing_custom_unsubscribe.unsubscribe");
|
||||||
|
|
||||||
// Allow to know if an element is required
|
// Allow to know if an element is required
|
||||||
$.extend($.expr[':'], {
|
$.extend($.expr[':'], {
|
||||||
propRequired: function(element, index, matches) {
|
propRequired: function(element, index, matches) {
|
||||||
return $(element).prop("required");
|
return $(element).prop("required");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Tour.register({
|
tour.register(
|
||||||
id: "mass_mailing_custom_unsubscribe_tour_partner",
|
"mass_mailing_custom_unsubscribe_tour_partner",
|
||||||
name: "Mass mailing partner unsubscribes",
|
{
|
||||||
mode: "test",
|
tour: true,
|
||||||
steps: [
|
wait_for: base.ready(),
|
||||||
|
},
|
||||||
|
[
|
||||||
{
|
{
|
||||||
title: "Choose other reason",
|
content: "Choose other reason",
|
||||||
element: ".radio:contains('Other reason') " +
|
trigger: ".radio:contains('Other reason') :radio:not(:checked)",
|
||||||
":radio:not(:checked)",
|
extra_trigger: "#reason_form .js_unsubscription_reason",
|
||||||
waitFor: "#reason_form .js_unsubscription_reason",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Switch to not interested reason",
|
content: "Switch to not interested reason",
|
||||||
element: ".radio:contains(\"I'm not interested\") " +
|
trigger: ".radio:contains(\"I'm not interested\") :radio:not(:checked)",
|
||||||
":radio:not(:checked)",
|
extra_trigger: "[name='details']:propRequired",
|
||||||
waitFor: "[name='details']:propRequired",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Unsubscribe",
|
content: "Unsubscribe",
|
||||||
element: "#reason_form :submit",
|
trigger: "#reason_form :submit",
|
||||||
waitNot: "[name='details']:propRequired",
|
extra_trigger: "body:not(:has([name='details']:propRequired))",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Successfully unsubscribed",
|
content: "Successfully unsubscribed",
|
||||||
waitFor: ".alert-success:contains(" +
|
trigger: "body:not(:has(#reason_form)) .alert-success:contains('Your changes have been saved.')",
|
||||||
"'Your changes have been saved.')",
|
|
||||||
waitNot: "#reason_form",
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
});
|
);
|
||||||
|
|
||||||
return Tour.tours.mass_mailing_custom_unsubscribe_tour_partner;
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,8 +7,11 @@ from openerp.tests.common import HttpCase
|
||||||
|
|
||||||
|
|
||||||
class UICase(HttpCase):
|
class UICase(HttpCase):
|
||||||
|
_tour_run = "odoo.__DEBUG__.services['web_tour.tour'].run('%s')"
|
||||||
|
_tour_ready = "odoo.__DEBUG__.services['web_tour.tour'].tours.%s.ready"
|
||||||
|
|
||||||
def extract_url(self, mail, *args, **kwargs):
|
def extract_url(self, mail, *args, **kwargs):
|
||||||
url = mail._get_unsubscribe_url(mail, self.email)
|
url = mail._get_unsubscribe_url(self.email)
|
||||||
self.assertIn("&token=", url)
|
self.assertIn("&token=", url)
|
||||||
self.assertTrue(url.startswith(self.domain))
|
self.assertTrue(url.startswith(self.domain))
|
||||||
self.url = url.replace(self.domain, "", 1)
|
self.url = url.replace(self.domain, "", 1)
|
||||||
|
@ -20,6 +23,7 @@ class UICase(HttpCase):
|
||||||
self.mail_postprocess_patch = mock.patch(
|
self.mail_postprocess_patch = mock.patch(
|
||||||
"openerp.addons.mass_mailing.models.mail_mail.MailMail."
|
"openerp.addons.mass_mailing.models.mail_mail.MailMail."
|
||||||
"_postprocess_sent_message",
|
"_postprocess_sent_message",
|
||||||
|
autospec=True,
|
||||||
side_effect=self.extract_url,
|
side_effect=self.extract_url,
|
||||||
)
|
)
|
||||||
with self.tempenv() as env:
|
with self.tempenv() as env:
|
||||||
|
@ -37,11 +41,7 @@ class UICase(HttpCase):
|
||||||
"contact_list_ids": [(6, 0, self.lists.ids)],
|
"contact_list_ids": [(6, 0, self.lists.ids)],
|
||||||
"reply_to_mode": "thread",
|
"reply_to_mode": "thread",
|
||||||
})
|
})
|
||||||
self.mailings[n].write(
|
self.mailings[n]._onchange_model_and_list()
|
||||||
self.mailings[n].on_change_model_and_list(
|
|
||||||
self.mailings[n].mailing_model,
|
|
||||||
self.mailings[n].contact_list_ids.ids,
|
|
||||||
)["value"])
|
|
||||||
# HACK https://github.com/odoo/odoo/pull/14429
|
# HACK https://github.com/odoo/odoo/pull/14429
|
||||||
self.mailings[n].body_html = """
|
self.mailings[n].body_html = """
|
||||||
<div>
|
<div>
|
||||||
|
@ -86,13 +86,12 @@ class UICase(HttpCase):
|
||||||
tour = "mass_mailing_custom_unsubscribe_tour_contact"
|
tour = "mass_mailing_custom_unsubscribe_tour_contact"
|
||||||
self.phantom_js(
|
self.phantom_js(
|
||||||
url_path=self.url,
|
url_path=self.url,
|
||||||
code=("odoo.__DEBUG__.services['web.Tour']"
|
code=self._tour_run % tour,
|
||||||
".run('%s', 'test')") % tour,
|
ready=self._tour_ready % tour)
|
||||||
ready="odoo.__DEBUG__.services['web.Tour'].tours.%s" % tour)
|
|
||||||
|
|
||||||
# Check results from running tour
|
# Check results from running tour
|
||||||
with self.tempenv() as env:
|
with self.tempenv() as env:
|
||||||
self.assertFalse(self.contacts[0].opt_out)
|
self.assertTrue(self.contacts[0].opt_out)
|
||||||
self.assertTrue(self.contacts[1].opt_out)
|
self.assertTrue(self.contacts[1].opt_out)
|
||||||
self.assertFalse(self.contacts[2].opt_out)
|
self.assertFalse(self.contacts[2].opt_out)
|
||||||
unsubscriptions = env["mail.unsubscription"].search([
|
unsubscriptions = env["mail.unsubscription"].search([
|
||||||
|
@ -130,9 +129,8 @@ class UICase(HttpCase):
|
||||||
tour = "mass_mailing_custom_unsubscribe_tour_partner"
|
tour = "mass_mailing_custom_unsubscribe_tour_partner"
|
||||||
self.phantom_js(
|
self.phantom_js(
|
||||||
url_path=self.url,
|
url_path=self.url,
|
||||||
code=("odoo.__DEBUG__.services['web.Tour']"
|
code=self._tour_run % tour,
|
||||||
".run('%s', 'test')") % tour,
|
ready=self._tour_ready % tour)
|
||||||
ready="odoo.__DEBUG__.services['web.Tour'].tours.%s" % tour)
|
|
||||||
|
|
||||||
# Check results from running tour
|
# Check results from running tour
|
||||||
with self.tempenv() as env:
|
with self.tempenv() as env:
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
<field name="model">mail.unsubscription.reason</field>
|
<field name="model">mail.unsubscription.reason</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree>
|
<tree>
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="details_required"/>
|
<field name="details_required"/>
|
||||||
<field name="sequence" invisible="True"/>
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
Loading…
Reference in New Issue