[IMP] mass_mailing_custom_unsubscribe: black, isort, prettier
This commit is contained in:
parent
9cdbc02cfc
commit
844c382fe7
@ -3,32 +3,25 @@
|
||||
# Copyright 2020 Tecnativa - Pedro M. Baeza
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
{
|
||||
'name': 'Customizable unsubscription process on mass mailing emails',
|
||||
'summary': 'Know and track (un)subscription reasons, GDPR compliant',
|
||||
'category': 'Marketing',
|
||||
'version': '12.0.1.0.2',
|
||||
'depends': [
|
||||
'mass_mailing',
|
||||
"name": "Customizable unsubscription process on mass mailing emails",
|
||||
"summary": "Know and track (un)subscription reasons, GDPR compliant",
|
||||
"category": "Marketing",
|
||||
"version": "12.0.1.0.2",
|
||||
"depends": ["mass_mailing"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"data/mail_unsubscription_reason.xml",
|
||||
"templates/general_reason_form.xml",
|
||||
"templates/mass_mailing_contact_reason.xml",
|
||||
"views/assets.xml",
|
||||
"views/mail_unsubscription_reason_view.xml",
|
||||
"views/mail_mass_mailing_list_view.xml",
|
||||
"views/mail_unsubscription_view.xml",
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'data/mail_unsubscription_reason.xml',
|
||||
'templates/general_reason_form.xml',
|
||||
'templates/mass_mailing_contact_reason.xml',
|
||||
'views/assets.xml',
|
||||
'views/mail_unsubscription_reason_view.xml',
|
||||
'views/mail_mass_mailing_list_view.xml',
|
||||
'views/mail_unsubscription_view.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/assets.xml',
|
||||
],
|
||||
'images': [
|
||||
'images/form.png',
|
||||
],
|
||||
'author': 'Tecnativa,'
|
||||
'Odoo Community Association (OCA)',
|
||||
'website': 'https://github.com/OCA/social',
|
||||
'license': 'AGPL-3',
|
||||
'installable': True,
|
||||
"demo": ["demo/assets.xml"],
|
||||
"images": ["images/form.png"],
|
||||
"author": "Tecnativa," "Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/social",
|
||||
"license": "AGPL-3",
|
||||
"installable": True,
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
import logging
|
||||
|
||||
from odoo.http import request, route
|
||||
|
||||
from odoo.addons.mass_mailing.controllers.main import MassMailController
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@ -35,14 +36,15 @@ class CustomUnsubscribe(MassMailController):
|
||||
"reasons": reasons,
|
||||
"res_id": res_id,
|
||||
"token": token,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
@route()
|
||||
def mailing(self, mailing_id, email=None, res_id=None, token="", **post):
|
||||
"""Ask/save unsubscription reason."""
|
||||
_logger.debug(
|
||||
"Called `mailing()` with: %r",
|
||||
(mailing_id, email, res_id, token, post))
|
||||
"Called `mailing()` with: %r", (mailing_id, email, res_id, token, post)
|
||||
)
|
||||
reasons = request.env["mail.unsubscription.reason"].search([])
|
||||
res_id = res_id and int(res_id)
|
||||
try:
|
||||
@ -55,67 +57,89 @@ class CustomUnsubscribe(MassMailController):
|
||||
# Unsubscribe, saving reason and details by context
|
||||
details = post.get("details", False)
|
||||
self._add_extra_context(mailing_id, res_id, reason_id, details)
|
||||
mailing_obj = request.env['mail.mass_mailing']
|
||||
mailing_obj = request.env["mail.mass_mailing"]
|
||||
mass_mailing = mailing_obj.sudo().browse(mailing_id)
|
||||
model = mass_mailing.mailing_model_real
|
||||
if ("opt_out" in request.env[model]._fields and
|
||||
model != "mail.mass_mailing.contact"):
|
||||
if (
|
||||
"opt_out" in request.env[model]._fields
|
||||
and model != "mail.mass_mailing.contact"
|
||||
):
|
||||
mass_mailing.update_opt_out_other(email, [res_id], True)
|
||||
result = request.render("mass_mailing.page_unsubscribed", {
|
||||
"email": email,
|
||||
"mailing_id": mailing_id,
|
||||
"res_id": res_id,
|
||||
"show_blacklist_button": request.env[
|
||||
"ir.config_parameter"
|
||||
].sudo().get_param(
|
||||
"mass_mailing.show_blacklist_buttons"
|
||||
),
|
||||
})
|
||||
result = request.render(
|
||||
"mass_mailing.page_unsubscribed",
|
||||
{
|
||||
"email": email,
|
||||
"mailing_id": mailing_id,
|
||||
"res_id": res_id,
|
||||
"show_blacklist_button": request.env["ir.config_parameter"]
|
||||
.sudo()
|
||||
.get_param("mass_mailing.show_blacklist_buttons"),
|
||||
},
|
||||
)
|
||||
result.qcontext.update({"reasons": reasons})
|
||||
else:
|
||||
# You could get a DetailsRequiredError here, but only if HTML5
|
||||
# validation fails, which should not happen in modern browsers
|
||||
result = super().mailing(
|
||||
mailing_id, email, res_id, token=token, **post)
|
||||
result = super().mailing(mailing_id, email, res_id, token=token, **post)
|
||||
if model == "mail.mass_mailing.contact":
|
||||
# update list_ids taking into account
|
||||
# not_cross_unsubscriptable field
|
||||
result.qcontext.update({
|
||||
"reasons": reasons,
|
||||
"list_ids": result.qcontext["list_ids"].filtered(
|
||||
lambda mailing_list:
|
||||
not mailing_list.not_cross_unsubscriptable or
|
||||
mailing_list in mass_mailing.contact_list_ids
|
||||
)
|
||||
})
|
||||
result.qcontext.update(
|
||||
{
|
||||
"reasons": reasons,
|
||||
"list_ids": result.qcontext["list_ids"].filtered(
|
||||
lambda m_list: not m_list.not_cross_unsubscriptable
|
||||
or m_list in mass_mailing.contact_list_ids
|
||||
),
|
||||
}
|
||||
)
|
||||
return result
|
||||
|
||||
@route()
|
||||
def unsubscribe(self, mailing_id, opt_in_ids, opt_out_ids, email, res_id,
|
||||
token, reason_id=None, details=None):
|
||||
def unsubscribe(
|
||||
self,
|
||||
mailing_id,
|
||||
opt_in_ids,
|
||||
opt_out_ids,
|
||||
email,
|
||||
res_id,
|
||||
token,
|
||||
reason_id=None,
|
||||
details=None,
|
||||
):
|
||||
"""Store unsubscription reasons when unsubscribing from RPC."""
|
||||
# Update request context
|
||||
self._add_extra_context(mailing_id, res_id, reason_id, details)
|
||||
_logger.debug(
|
||||
"Called `unsubscribe()` with: %r",
|
||||
(mailing_id, opt_in_ids, opt_out_ids, email, res_id, token,
|
||||
reason_id, details))
|
||||
(
|
||||
mailing_id,
|
||||
opt_in_ids,
|
||||
opt_out_ids,
|
||||
email,
|
||||
res_id,
|
||||
token,
|
||||
reason_id,
|
||||
details,
|
||||
),
|
||||
)
|
||||
return super().unsubscribe(
|
||||
mailing_id, opt_in_ids, opt_out_ids, email, res_id, token)
|
||||
mailing_id, opt_in_ids, opt_out_ids, email, res_id, token
|
||||
)
|
||||
|
||||
@route()
|
||||
def blacklist_add(self, mailing_id, res_id, email, token, reason_id=None,
|
||||
details=None):
|
||||
def blacklist_add(
|
||||
self, mailing_id, res_id, email, token, reason_id=None, details=None
|
||||
):
|
||||
self._add_extra_context(mailing_id, res_id, reason_id, details)
|
||||
return super().blacklist_add(
|
||||
mailing_id, res_id, email, token)
|
||||
return super().blacklist_add(mailing_id, res_id, email, token)
|
||||
|
||||
@route()
|
||||
def blacklist_remove(self, mailing_id, res_id, email, token,
|
||||
reason_id=None, details=None):
|
||||
def blacklist_remove(
|
||||
self, mailing_id, res_id, email, token, reason_id=None, details=None
|
||||
):
|
||||
self._add_extra_context(mailing_id, res_id, reason_id, details)
|
||||
return super().blacklist_remove(
|
||||
mailing_id, res_id, email, token)
|
||||
return super().blacklist_remove(mailing_id, res_id, email, token)
|
||||
|
||||
def _add_extra_context(self, mailing_id, res_id, reason_id, details):
|
||||
environ = request.httprequest.headers.environ
|
||||
@ -123,11 +147,8 @@ class CustomUnsubscribe(MassMailController):
|
||||
# redefinition of _add and _remove methods of the mail.blacklist class
|
||||
extra_context = {
|
||||
"default_metadata": "\n".join(
|
||||
"%s: %s" % (val, environ.get(val)) for val in (
|
||||
"REMOTE_ADDR",
|
||||
"HTTP_USER_AGENT",
|
||||
"HTTP_ACCEPT_LANGUAGE",
|
||||
)
|
||||
"{}: {}".format(val, environ.get(val))
|
||||
for val in ("REMOTE_ADDR", "HTTP_USER_AGENT", "HTTP_ACCEPT_LANGUAGE")
|
||||
),
|
||||
"mailing_id": mailing_id,
|
||||
"unsubscription_res_id": int(res_id),
|
||||
|
@ -5,34 +5,36 @@ from odoo import models
|
||||
|
||||
|
||||
class MailBlackList(models.Model):
|
||||
_inherit = 'mail.blacklist'
|
||||
_inherit = "mail.blacklist"
|
||||
|
||||
def _add(self, email):
|
||||
mailing_id = self.env.context.get('mailing_id')
|
||||
res_id = self.env.context.get('unsubscription_res_id')
|
||||
mailing_id = self.env.context.get("mailing_id")
|
||||
res_id = self.env.context.get("unsubscription_res_id")
|
||||
if mailing_id and res_id:
|
||||
mailing = self.env['mail.mass_mailing'].browse(mailing_id,
|
||||
self._prefetch)
|
||||
mailing = self.env["mail.mass_mailing"].browse(mailing_id, self._prefetch)
|
||||
model_name = mailing.mailing_model_real
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": email,
|
||||
"mass_mailing_id": mailing_id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, res_id),
|
||||
"action": "blacklist_add",
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": email,
|
||||
"mass_mailing_id": mailing_id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, res_id),
|
||||
"action": "blacklist_add",
|
||||
}
|
||||
)
|
||||
return super()._add(email)
|
||||
|
||||
def _remove(self, email):
|
||||
mailing_id = self.env.context.get('mailing_id')
|
||||
res_id = self.env.context.get('unsubscription_res_id')
|
||||
mailing_id = self.env.context.get("mailing_id")
|
||||
res_id = self.env.context.get("unsubscription_res_id")
|
||||
if mailing_id and res_id:
|
||||
mailing = self.env['mail.mass_mailing'].browse(mailing_id,
|
||||
self._prefetch)
|
||||
mailing = self.env["mail.mass_mailing"].browse(mailing_id, self._prefetch)
|
||||
model_name = mailing.mailing_model_real
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": email,
|
||||
"mass_mailing_id": mailing_id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, res_id),
|
||||
"action": "blacklist_rm",
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": email,
|
||||
"mass_mailing_id": mailing_id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, res_id),
|
||||
"action": "blacklist_rm",
|
||||
}
|
||||
)
|
||||
return super()._remove(email)
|
||||
|
@ -2,9 +2,10 @@
|
||||
# Copyright 2020 Tecnativa - Pedro M. Baeza
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from itertools import groupby
|
||||
|
||||
from odoo import models, tools
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
from itertools import groupby
|
||||
|
||||
|
||||
class MailMassMailing(models.Model):
|
||||
@ -14,61 +15,65 @@ class MailMassMailing(models.Model):
|
||||
"""Save unsubscription reason when opting out from mailing."""
|
||||
self.ensure_one()
|
||||
action = "unsubscription" if value else "subscription"
|
||||
subscription_model = self.env['mail.mass_mailing.list_contact_rel']
|
||||
opt_out_records = subscription_model.search([
|
||||
('contact_id.email', '=ilike', email),
|
||||
('list_id', 'in', list_ids),
|
||||
('opt_out', '!=', value),
|
||||
])
|
||||
model_name = 'mail.mass_mailing.contact'
|
||||
for contact, subscriptions in groupby(opt_out_records,
|
||||
lambda r: r.contact_id):
|
||||
subscription_model = self.env["mail.mass_mailing.list_contact_rel"]
|
||||
opt_out_records = subscription_model.search(
|
||||
[
|
||||
("contact_id.email", "=ilike", email),
|
||||
("list_id", "in", list_ids),
|
||||
("opt_out", "!=", value),
|
||||
]
|
||||
)
|
||||
model_name = "mail.mass_mailing.contact"
|
||||
for contact, subscriptions in groupby(opt_out_records, lambda r: r.contact_id):
|
||||
mailing_list_ids = [r.list_id.id for r in subscriptions]
|
||||
# reason_id and details are expected from the context
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": email,
|
||||
"mass_mailing_id": self.id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, contact.id),
|
||||
'mailing_list_ids': [(6, False, mailing_list_ids)],
|
||||
"action": action,
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": email,
|
||||
"mass_mailing_id": self.id,
|
||||
"unsubscriber_id": "%s,%d" % (model_name, contact.id),
|
||||
"mailing_list_ids": [(6, False, mailing_list_ids)],
|
||||
"action": action,
|
||||
}
|
||||
)
|
||||
return super().update_opt_out(email, list_ids, value)
|
||||
|
||||
def update_opt_out_other(self, email, res_ids, value):
|
||||
"""Method for changing unsubscription for models with opt_out field."""
|
||||
model = self.env[self.mailing_model_real].with_context(
|
||||
active_test=False)
|
||||
model = self.env[self.mailing_model_real].with_context(active_test=False)
|
||||
action = "unsubscription" if value else "subscription"
|
||||
if 'opt_out' in model._fields:
|
||||
email_fname = 'email_from'
|
||||
if 'email' in model._fields:
|
||||
email_fname = 'email'
|
||||
records = model.search([
|
||||
('id', 'in', res_ids), (email_fname, 'ilike', email)])
|
||||
records.write({'opt_out': value})
|
||||
if "opt_out" in model._fields:
|
||||
email_fname = "email_from"
|
||||
if "email" in model._fields:
|
||||
email_fname = "email"
|
||||
records = model.search(
|
||||
[("id", "in", res_ids), (email_fname, "ilike", email)]
|
||||
)
|
||||
records.write({"opt_out": value})
|
||||
for res_id in res_ids:
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": email,
|
||||
"mass_mailing_id": self.id,
|
||||
"unsubscriber_id": "%s,%d" % (
|
||||
self.mailing_model_real, res_id),
|
||||
"action": action,
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": email,
|
||||
"mass_mailing_id": self.id,
|
||||
"unsubscriber_id": "%s,%d" % (self.mailing_model_real, res_id),
|
||||
"action": action,
|
||||
}
|
||||
)
|
||||
|
||||
def _get_opt_out_list(self):
|
||||
"""Handle models with opt_out field for excluding them."""
|
||||
self.ensure_one()
|
||||
model = self.env[self.mailing_model_real].with_context(
|
||||
active_test=False)
|
||||
if (self.mailing_model_real != "mail.mass_mailing.contact" and
|
||||
'opt_out' in model._fields):
|
||||
email_fname = 'email_from'
|
||||
if 'email' in model._fields:
|
||||
email_fname = 'email'
|
||||
model = self.env[self.mailing_model_real].with_context(active_test=False)
|
||||
if (
|
||||
self.mailing_model_real != "mail.mass_mailing.contact"
|
||||
and "opt_out" in model._fields
|
||||
):
|
||||
email_fname = "email_from"
|
||||
if "email" in model._fields:
|
||||
email_fname = "email"
|
||||
domain = safe_eval(self.mailing_domain)
|
||||
domain = [('opt_out', '=', True)] + domain
|
||||
domain = [("opt_out", "=", True)] + domain
|
||||
recs = self.env[self.mailing_model_real].search(domain)
|
||||
normalized_email = (
|
||||
tools.email_split(c[email_fname]) for c in recs)
|
||||
return set(e[0].lower() for e in normalized_email if e)
|
||||
normalized_email = (tools.email_split(c[email_fname]) for c in recs)
|
||||
return {e[0].lower() for e in normalized_email if e}
|
||||
return super()._get_opt_out_list()
|
||||
|
@ -10,5 +10,6 @@ class MailMassMailing(models.Model):
|
||||
not_cross_unsubscriptable = fields.Boolean(
|
||||
string="Not cross unsubscriptable",
|
||||
help="If you mark this field, this list won't be shown when "
|
||||
"unsubscribing from other mailing list, in the section: "
|
||||
"'Is there any other mailing list you want to leave?'")
|
||||
"unsubscribing from other mailing list, in the section: "
|
||||
"'Is there any other mailing list you want to leave?'",
|
||||
)
|
||||
|
@ -2,8 +2,9 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.addons.mass_mailing.models.mass_mailing import \
|
||||
MASS_MAILING_BUSINESS_MODELS
|
||||
|
||||
from odoo.addons.mass_mailing.models.mass_mailing import MASS_MAILING_BUSINESS_MODELS
|
||||
|
||||
from .. import exceptions
|
||||
|
||||
|
||||
@ -14,11 +15,8 @@ class MailUnsubscription(models.Model):
|
||||
_rec_name = "date"
|
||||
_order = "date DESC"
|
||||
|
||||
date = fields.Datetime(
|
||||
default=lambda self: self._default_date(),
|
||||
required=True)
|
||||
email = fields.Char(
|
||||
required=True)
|
||||
date = fields.Datetime(default=lambda self: self._default_date(), required=True)
|
||||
email = fields.Char(required=True)
|
||||
action = fields.Selection(
|
||||
selection=[
|
||||
("subscription", "Subscription"),
|
||||
@ -34,11 +32,13 @@ class MailUnsubscription(models.Model):
|
||||
"mail.mass_mailing",
|
||||
"Mass mailing",
|
||||
required=True,
|
||||
help="Mass mailing from which he was unsubscribed.")
|
||||
help="Mass mailing from which he was unsubscribed.",
|
||||
)
|
||||
unsubscriber_id = fields.Reference(
|
||||
lambda self: self._selection_unsubscriber_id(),
|
||||
"(Un)subscriber",
|
||||
help="Who was subscribed or unsubscribed.")
|
||||
help="Who was subscribed or unsubscribed.",
|
||||
)
|
||||
mailing_list_ids = fields.Many2many(
|
||||
comodel_name="mail.mass_mailing.list",
|
||||
string="Mailing lists",
|
||||
@ -48,21 +48,19 @@ class MailUnsubscription(models.Model):
|
||||
"mail.unsubscription.reason",
|
||||
"Reason",
|
||||
ondelete="restrict",
|
||||
help="Why the unsubscription was made.")
|
||||
details = fields.Text(
|
||||
help="More details on why the unsubscription was made.")
|
||||
details_required = fields.Boolean(
|
||||
related="reason_id.details_required")
|
||||
help="Why the unsubscription was made.",
|
||||
)
|
||||
details = fields.Text(help="More details on why the unsubscription was made.")
|
||||
details_required = fields.Boolean(related="reason_id.details_required")
|
||||
metadata = fields.Text(
|
||||
readonly=True,
|
||||
help="HTTP request metadata used when creating this record.",
|
||||
readonly=True, help="HTTP request metadata used when creating this record."
|
||||
)
|
||||
|
||||
def map_mailing_list_models(self, models):
|
||||
model_mapped = []
|
||||
for model in models:
|
||||
if model == 'mail.mass_mailing.list':
|
||||
model_mapped.append(('mail.mass_mailing.contact', model))
|
||||
if model == "mail.mass_mailing.list":
|
||||
model_mapped.append(("mail.mass_mailing.contact", model))
|
||||
else:
|
||||
model_mapped.append((model, model))
|
||||
return model_mapped
|
||||
@ -74,8 +72,11 @@ class MailUnsubscription(models.Model):
|
||||
@api.model
|
||||
def _selection_unsubscriber_id(self):
|
||||
"""Models that can be linked to a ``mail.mass_mailing``."""
|
||||
model = self.env['ir.model'].search(
|
||||
[('model', 'in', MASS_MAILING_BUSINESS_MODELS)]).mapped('model')
|
||||
model = (
|
||||
self.env["ir.model"]
|
||||
.search([("model", "in", MASS_MAILING_BUSINESS_MODELS)])
|
||||
.mapped("model")
|
||||
)
|
||||
return self.map_mailing_list_models(model)
|
||||
|
||||
@api.multi
|
||||
@ -86,7 +87,8 @@ class MailUnsubscription(models.Model):
|
||||
unsubscription_states = {"unsubscription", "blacklist_add"}
|
||||
if one.action in unsubscription_states and not one.reason_id:
|
||||
raise exceptions.ReasonRequiredError(
|
||||
_("Please indicate why are you unsubscribing."))
|
||||
_("Please indicate why are you unsubscribing.")
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.constrains("details", "reason_id")
|
||||
@ -95,7 +97,8 @@ class MailUnsubscription(models.Model):
|
||||
for one in self:
|
||||
if not one.details and one.details_required:
|
||||
raise exceptions.DetailsRequiredError(
|
||||
_("Please provide details on why you are unsubscribing."))
|
||||
_("Please provide details on why you are unsubscribing.")
|
||||
)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@ -110,12 +113,8 @@ class MailUnsubscriptionReason(models.Model):
|
||||
_description = "Mail unsubscription reason"
|
||||
_order = "sequence, name"
|
||||
|
||||
name = fields.Char(
|
||||
index=True,
|
||||
translate=True,
|
||||
required=True)
|
||||
name = fields.Char(index=True, translate=True, required=True)
|
||||
details_required = fields.Boolean(
|
||||
help="Check to ask for more details when this reason is selected.")
|
||||
sequence = fields.Integer(
|
||||
index=True,
|
||||
help="Position of the reason in the list.")
|
||||
help="Check to ask for more details when this reason is selected."
|
||||
)
|
||||
sequence = fields.Integer(index=True, help="Position of the reason in the list.")
|
||||
|
@ -2,4 +2,5 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import test_ui
|
||||
|
||||
# from . import test_unsubscription
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
import mock
|
||||
from odoo.tests.common import HttpCase
|
||||
from werkzeug import urls
|
||||
|
||||
from odoo.tests.common import HttpCase
|
||||
|
||||
|
||||
class UICase(HttpCase):
|
||||
_tour_run = "odoo.__DEBUG__.services['web_tour.tour'].run('%s')"
|
||||
@ -11,7 +12,7 @@ class UICase(HttpCase):
|
||||
|
||||
def extract_url(self, mail, *args, **kwargs):
|
||||
url = mail._get_unsubscribe_url(self.email)
|
||||
self.assertTrue(urls.url_parse(url).decode_query().get('token'))
|
||||
self.assertTrue(urls.url_parse(url).decode_query().get("token"))
|
||||
self.assertTrue(url.startswith(self.domain))
|
||||
self.url = url.replace(self.domain, "", 1)
|
||||
return True
|
||||
@ -26,24 +27,27 @@ class UICase(HttpCase):
|
||||
side_effect=self.extract_url,
|
||||
)
|
||||
|
||||
self.domain = self.env["ir.config_parameter"].get_param('web.base.url')
|
||||
self.domain = self.env["ir.config_parameter"].get_param("web.base.url")
|
||||
List = self.lists = self.env["mail.mass_mailing.list"]
|
||||
for n in range(4):
|
||||
self.lists += List.create({"name": "test list %d" % n})
|
||||
self.contact = self.env["mail.mass_mailing.contact"].create({
|
||||
"name": "test contact",
|
||||
"email": self.email,
|
||||
"list_ids": [(6, False, self.lists.ids)],
|
||||
})
|
||||
self.mailing = self.env["mail.mass_mailing"].create({
|
||||
"name": "test mailing %d" % n,
|
||||
"mailing_model_id": self.env.ref(
|
||||
'mass_mailing.model_mail_mass_mailing_list').id,
|
||||
"contact_list_ids": [
|
||||
(6, 0, [self.lists[0].id, self.lists[3].id])
|
||||
],
|
||||
"reply_to_mode": "thread",
|
||||
})
|
||||
self.contact = self.env["mail.mass_mailing.contact"].create(
|
||||
{
|
||||
"name": "test contact",
|
||||
"email": self.email,
|
||||
"list_ids": [(6, False, self.lists.ids)],
|
||||
}
|
||||
)
|
||||
self.mailing = self.env["mail.mass_mailing"].create(
|
||||
{
|
||||
"name": "test mailing %d" % n,
|
||||
"mailing_model_id": self.env.ref(
|
||||
"mass_mailing.model_mail_mass_mailing_list"
|
||||
).id,
|
||||
"contact_list_ids": [(6, 0, [self.lists[0].id, self.lists[3].id])],
|
||||
"reply_to_mode": "thread",
|
||||
}
|
||||
)
|
||||
self.mailing._onchange_model_and_list()
|
||||
# HACK https://github.com/odoo/odoo/pull/14429
|
||||
self.mailing.body_html = """
|
||||
@ -76,7 +80,8 @@ class UICase(HttpCase):
|
||||
url_path=self.url,
|
||||
code=self._tour_run % tour,
|
||||
ready=self._tour_ready % tour,
|
||||
login='demo')
|
||||
login="demo",
|
||||
)
|
||||
|
||||
# Check results from running tour
|
||||
self.assertFalse(self.lists[0].subscription_contact_ids.opt_out)
|
||||
@ -92,32 +97,31 @@ class UICase(HttpCase):
|
||||
# first unsubscription
|
||||
reason = "mass_mailing_custom_unsubscribe.reason_other"
|
||||
unsubscription_1 = self.env["mail.unsubscription"].search(
|
||||
common_domain + [
|
||||
common_domain
|
||||
+ [
|
||||
("action", "=", "unsubscription"),
|
||||
("details", "=", "I want to unsubscribe because I want. "
|
||||
"Period."),
|
||||
("details", "=", "I want to unsubscribe because I want. " "Period."),
|
||||
("reason_id", "=", self.env.ref(reason).id),
|
||||
]
|
||||
)
|
||||
# second unsubscription
|
||||
reason = "mass_mailing_custom_unsubscribe.reason_not_interested"
|
||||
unsubscription_2 = self.env["mail.unsubscription"].search(
|
||||
common_domain + [
|
||||
common_domain
|
||||
+ [
|
||||
("action", "=", "unsubscription"),
|
||||
("reason_id", "=", self.env.ref(reason).id),
|
||||
]
|
||||
)
|
||||
# re-subscription from self.lists[3]
|
||||
unsubscription_3 = self.env["mail.unsubscription"].search(
|
||||
common_domain + [
|
||||
("action", "=", "subscription"),
|
||||
]
|
||||
common_domain + [("action", "=", "subscription")]
|
||||
)
|
||||
# unsubscriptions above are all unsubscriptions saved during the
|
||||
# tour and they are all the existing unsubscriptions
|
||||
self.assertEqual(
|
||||
unsubscription_1 | unsubscription_2 | unsubscription_3,
|
||||
self.env["mail.unsubscription"].search([])
|
||||
self.env["mail.unsubscription"].search([]),
|
||||
)
|
||||
self.assertEqual(3, len(self.env["mail.unsubscription"].search([])))
|
||||
|
||||
@ -125,13 +129,12 @@ class UICase(HttpCase):
|
||||
"""Test a partner that wants to unsubscribe."""
|
||||
# Change mailing to be sent to partner
|
||||
partner_id = self.env["res.partner"].name_create(
|
||||
"Demo Partner <%s>" % self.email)[0]
|
||||
self.mailing.mailing_model_id = self.env.ref(
|
||||
"base.model_res_partner")
|
||||
self.mailing.mailing_domain = repr([
|
||||
('is_blacklisted', '=', False),
|
||||
('id', '=', partner_id),
|
||||
])
|
||||
"Demo Partner <%s>" % self.email
|
||||
)[0]
|
||||
self.mailing.mailing_model_id = self.env.ref("base.model_res_partner")
|
||||
self.mailing.mailing_domain = repr(
|
||||
[("is_blacklisted", "=", False), ("id", "=", partner_id)]
|
||||
)
|
||||
# Extract the unsubscription link from the message body
|
||||
with self.mail_postprocess_patch:
|
||||
self.mailing.send_mail()
|
||||
@ -141,18 +144,21 @@ class UICase(HttpCase):
|
||||
url_path=self.url,
|
||||
code=self._tour_run % tour,
|
||||
ready=self._tour_ready % tour,
|
||||
login='demo')
|
||||
login="demo",
|
||||
)
|
||||
|
||||
# Check results from running tour
|
||||
partner = self.env["res.partner"].browse(partner_id)
|
||||
self.assertTrue(partner.is_blacklisted)
|
||||
reason_xid = "mass_mailing_custom_unsubscribe.reason_not_interested"
|
||||
unsubscriptions = self.env["mail.unsubscription"].search([
|
||||
("action", "=", 'blacklist_add'),
|
||||
("mass_mailing_id", "=", self.mailing.id),
|
||||
("email", "=", self.email),
|
||||
("unsubscriber_id", "=", "res.partner,%d" % partner_id),
|
||||
("details", "=", False),
|
||||
("reason_id", "=", self.env.ref(reason_xid).id),
|
||||
])
|
||||
unsubscriptions = self.env["mail.unsubscription"].search(
|
||||
[
|
||||
("action", "=", "blacklist_add"),
|
||||
("mass_mailing_id", "=", self.mailing.id),
|
||||
("email", "=", self.email),
|
||||
("unsubscriber_id", "=", "res.partner,%d" % partner_id),
|
||||
("details", "=", False),
|
||||
("reason_id", "=", self.env.ref(reason_xid).id),
|
||||
]
|
||||
)
|
||||
self.assertEqual(1, len(unsubscriptions))
|
||||
|
@ -2,6 +2,7 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import SavepointCase
|
||||
|
||||
from .. import exceptions
|
||||
|
||||
|
||||
@ -9,22 +10,26 @@ class UnsubscriptionCase(SavepointCase):
|
||||
def test_details_required(self):
|
||||
"""Cannot create unsubscription without details when required."""
|
||||
with self.assertRaises(exceptions.DetailsRequiredError):
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": "axelor@yourcompany.example.com",
|
||||
"mass_mailing_id": self.env.ref("mass_mailing.mass_mail_1").id,
|
||||
"unsubscriber_id":
|
||||
"res.partner,%d" % self.env.ref("base.res_partner_2").id,
|
||||
"reason_id":
|
||||
self.env.ref(
|
||||
"mass_mailing_custom_unsubscribe.reason_other").id,
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": "axelor@yourcompany.example.com",
|
||||
"mass_mailing_id": self.env.ref("mass_mailing.mass_mail_1").id,
|
||||
"unsubscriber_id": "res.partner,%d"
|
||||
% self.env.ref("base.res_partner_2").id,
|
||||
"reason_id": self.env.ref(
|
||||
"mass_mailing_custom_unsubscribe.reason_other"
|
||||
).id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_reason_required(self):
|
||||
"""Cannot create unsubscription without reason when required."""
|
||||
with self.assertRaises(exceptions.ReasonRequiredError):
|
||||
self.env["mail.unsubscription"].create({
|
||||
"email": "axelor@yourcompany.example.com",
|
||||
"mass_mailing_id": self.env.ref("mass_mailing.mass_mail_1").id,
|
||||
"unsubscriber_id":
|
||||
"res.partner,%d" % self.env.ref("base.res_partner_2").id,
|
||||
})
|
||||
self.env["mail.unsubscription"].create(
|
||||
{
|
||||
"email": "axelor@yourcompany.example.com",
|
||||
"mass_mailing_id": self.env.ref("mass_mailing.mass_mail_1").id,
|
||||
"unsubscriber_id": "res.partner,%d"
|
||||
% self.env.ref("base.res_partner_2").id,
|
||||
}
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user