[REF] mass_mailing: rename mail.mass_mailing.{.contact{_rel}, list{.merge}} models

PURPOSE

Mass mailing is currently a bit messy. As SMS will be added as a way to notify
people in mass through SMS let us take this opportunity to somehow clean this
application: organization, light code cleaning, model renaming.

SPECIFICATIONS

Rename mail.mass_mailing.list and mail.mass_mailing.list to mailing.list
and mailing.list.merge. Rename mail.mass_mailing.contact to mailing.contact.
Rename mail.mailing_list.list_contact_rel to mailing.contact.subscription.
Rationale :

  * those new names are easier to understand: mailing.list and mailing.contact
    are less mail-related, especially taking into account that SMS will allow
    to be less mail-oriented;
  * those names are easier to read / find / understand;
  * align wizard and sub-models naming with the main naming;
  * have a mailing as first part of namespacing;

MIGRATION

mail.mass_mailing.list model -> mailing.list
mail.mass_mailing.list.merge model -> mailing.list.merge
mail.mass_mailing.contact model -> mailing.contact
mail.mass_mailing.list_contact_rel model -> mailing.contact.subscription
mail_mass_mailing_contact_list_rel table -> mailing_contact_list_rel (specific
case of a decorated m2m)

fields updated (no column change)
  * mailing.list: subscription_contact_ids -> subscription_ids

LINKS

Task ID 2037906
Preparing task ID 1997464 (SMS addition in mass mailing)
PR #34938
This commit is contained in:
Thibault Delavallée
2019-07-17 15:50:33 +00:00
parent 2896aad34e
commit 772e1c0cc4
28 changed files with 193 additions and 190 deletions
+3 -3
View File
@@ -24,14 +24,14 @@
'data/mail_data.xml',
'data/mass_mailing_data.xml',
'wizard/mail_compose_message_views.xml',
'wizard/mass_mailing_list_merge_views.xml',
'wizard/mailing_list_merge_views.xml',
'wizard/test_mailing_views.xml',
'wizard/mass_mailing_schedule_date_views.xml',
'views/mass_mailing_views_menus.xml',
'views/mailing_trace_views.xml',
'views/link_tracker_views.xml',
'views/mass_mailing_contact_views.xml',
'views/mass_mailing_list_views.xml',
'views/mailing_contact_views.xml',
'views/mailing_list_views.xml',
'views/mass_mailing_views.xml',
'views/res_config_settings_views.xml',
'report/mailing_trace_report_views.xml',
+4 -4
View File
@@ -35,11 +35,11 @@ class MassMailController(http.Controller):
if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)):
raise exceptions.AccessDenied()
if mailing.mailing_model_real == 'mail.mass_mailing.contact':
if mailing.mailing_model_real == 'mailing.contact':
# Unsubscribe directly + Let the user choose his subscriptions
mailing.update_opt_out(email, mailing.contact_list_ids.ids, True)
contacts = request.env['mail.mass_mailing.contact'].sudo().search([('email_normalized', '=', tools.email_normalize(email))])
contacts = request.env['mailing.contact'].sudo().search([('email_normalized', '=', tools.email_normalize(email))])
subscription_list_ids = contacts.mapped('subscription_list_ids')
# In many user are found : if user is opt_out on the list with contact_id 1 but not with contact_id 2,
# assume that the user is not opt_out on both
@@ -49,7 +49,7 @@ class MassMailController(http.Controller):
opt_out_list_ids = set([list.id for list in opt_out_list_ids if list not in opt_in_list_ids])
unique_list_ids = set([list.list_id.id for list in subscription_list_ids])
list_ids = request.env['mail.mass_mailing.list'].sudo().browse(unique_list_ids)
list_ids = request.env['mailing.list'].sudo().browse(unique_list_ids)
unsubscribed_list = ', '.join(str(list.name) for list in mailing.contact_list_ids if list.is_public)
return request.render('mass_mailing.page_unsubscribe', {
'contacts': contacts,
@@ -62,7 +62,7 @@ class MassMailController(http.Controller):
'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'),
})
else:
opt_in_lists = request.env['mail.mass_mailing.list_contact_rel'].sudo().search([
opt_in_lists = request.env['mailing.contact.subscription'].sudo().search([
('contact_id.email_normalized', '=', email),
('opt_out', '=', False)
]).mapped('list_id')
@@ -8,38 +8,38 @@
</record>
<!-- Create mailing lists -->
<record id="mass_mail_list_2" model="mail.mass_mailing.list">
<record id="mass_mail_list_2" model="mailing.list">
<field name="name">Imported Contacts</field>
</record>
<!-- Create Contacts -->
<record id="mass_mail_contact_1" model="mail.mass_mailing.contact">
<record id="mass_mail_contact_1" model="mailing.contact">
<field name="name">Aristide Antario</field>
<field name="email">aa@example.com</field>
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mass_mail_list_2')])]"/>
</record>
<record id="mass_mail_contact_2" model="mail.mass_mailing.contact">
<record id="mass_mail_contact_2" model="mailing.contact">
<field name="name">Beverly Bridge</field>
<field name="email">bb@example.com</field>
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mass_mail_list_2')])]"/>
</record>
<record id="mass_mail_contact_3" model="mail.mass_mailing.contact">
<record id="mass_mail_contact_3" model="mailing.contact">
<field name="name">Carol Cartridge</field>
<field name="email">cc@example.com</field>
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mass_mail_list_2')])]"/>
</record>
<record id="mass_mail_contact_4" model="mail.mass_mailing.contact">
<record id="mass_mail_contact_4" model="mailing.contact">
<field name="name">David Dawson</field>
<field name="email">dd@example.com</field>
</record>
<record id="mass_mail_contact_5" model="mail.mass_mailing.contact">
<record id="mass_mail_contact_5" model="mailing.contact">
<field name="name">Elsa Ericson</field>
<field name="email">ee@example.com</field>
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mass_mail_list_2')])]"/>
</record>
<!-- Create Opt-out Records -->
<record id="mass_mail_contact_list_rel_1" model="mail.mass_mailing.list_contact_rel">
<record id="mass_mail_contact_list_rel_1" model="mailing.contact.subscription">
<field name="list_id" eval="ref('mass_mailing.mass_mail_list_2')"/>
<field name="contact_id" eval="ref('mass_mailing.mass_mail_contact_4')"/>
<field name="opt_out">True</field>
+2 -2
View File
@@ -2,8 +2,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import link_tracker
from . import mass_mailing_contact
from . import mass_mailing_list
from . import mailing_contact
from . import mailing_list
from . import mass_mailing
from . import mailing_trace
from . import mail_mail
@@ -9,13 +9,13 @@ class MassMailingContactListRel(models.Model):
""" Intermediate model between mass mailing list and mass mailing contact
Indicates if a contact is opted out for a particular list
"""
_name = 'mail.mass_mailing.list_contact_rel'
_name = 'mailing.contact.subscription'
_description = 'Mass Mailing Subscription Information'
_table = 'mail_mass_mailing_contact_list_rel'
_table = 'mailing_contact_list_rel'
_rec_name = 'contact_id'
contact_id = fields.Many2one('mail.mass_mailing.contact', string='Contact', ondelete='cascade', required=True)
list_id = fields.Many2one('mail.mass_mailing.list', string='Mailing List', ondelete='cascade', required=True)
contact_id = fields.Many2one('mailing.contact', string='Contact', ondelete='cascade', required=True)
list_id = fields.Many2one('mailing.list', string='Mailing List', ondelete='cascade', required=True)
opt_out = fields.Boolean(string='Opt Out',
help='The contact has chosen not to receive mails anymore from this list', default=False)
unsubscription_date = fields.Datetime(string='Unsubscription Date')
@@ -45,7 +45,7 @@ class MassMailingContactListRel(models.Model):
action = {
'name': _(contact_id.name),
'type': 'ir.actions.act_window',
'res_model': 'mail.mass_mailing.contact',
'res_model': 'mailing.contact',
'view_mode': 'form',
'target': 'current',
'res_id': contact_id.id
@@ -58,7 +58,7 @@ class MassMailingContact(models.Model):
because it holds only some basic information: name, email. The purpose is to
be able to deal with large contact list to email without bloating the partner
base."""
_name = 'mail.mass_mailing.contact'
_name = 'mailing.contact'
_inherit = ['mail.thread.blacklist']
_description = 'Mass Mailing Contact'
_order = 'email'
@@ -70,10 +70,9 @@ class MassMailingContact(models.Model):
email = fields.Char(required=True)
is_email_valid = fields.Boolean(compute='_compute_is_email_valid', store=True)
list_ids = fields.Many2many(
'mail.mass_mailing.list', 'mail_mass_mailing_contact_list_rel',
'mailing.list', 'mailing_contact_list_rel',
'contact_id', 'list_id', string='Mailing Lists')
subscription_list_ids = fields.One2many('mail.mass_mailing.list_contact_rel',
'contact_id', string='Subscription Information')
subscription_list_ids = fields.One2many('mailing.contact.subscription', 'contact_id', string='Subscription Information')
country_id = fields.Many2one('res.country', string='Country')
tag_ids = fields.Many2many('res.partner.category', string='Tags')
opt_out = fields.Boolean('Opt Out', compute='_compute_opt_out', search='_search_opt_out',
@@ -97,7 +96,7 @@ class MassMailingContact(models.Model):
if 'default_list_ids' in self._context and isinstance(self._context['default_list_ids'], (list, tuple)) and len(self._context['default_list_ids']) == 1:
[active_list_id] = self._context['default_list_ids']
contacts = self.env['mail.mass_mailing.list_contact_rel'].search([('list_id', '=', active_list_id)])
contacts = self.env['mailing.contact.subscription'].search([('list_id', '=', active_list_id)])
return [('id', 'in', [record.contact_id.id for record in contacts if record.opt_out == value])]
else:
raise UserError('Search opt out cannot be executed without a unique and valid active mailing list context.')
@@ -6,7 +6,7 @@ from odoo import api, fields, models
class MassMailingList(models.Model):
"""Model of a contact list. """
_name = 'mail.mass_mailing.list'
_name = 'mailing.list'
_order = 'name'
_description = 'Mailing List'
@@ -14,9 +14,9 @@ class MassMailingList(models.Model):
active = fields.Boolean(default=True)
contact_nbr = fields.Integer(compute="_compute_contact_nbr", string='Number of Contacts')
contact_ids = fields.Many2many(
'mail.mass_mailing.contact', 'mail_mass_mailing_contact_list_rel', 'list_id', 'contact_id',
'mailing.contact', 'mailing_contact_list_rel', 'list_id', 'contact_id',
string='Mailing Lists')
subscription_contact_ids = fields.One2many('mail.mass_mailing.list_contact_rel', 'list_id',
subscription_ids = fields.One2many('mailing.contact.subscription', 'list_id',
string='Subscription Information')
is_public = fields.Boolean(default=True, help="The mailing list can be accessible by recipient in the unsubscription"
" page to allows him to update his subscription preferences.")
@@ -27,8 +27,8 @@ class MassMailingList(models.Model):
select
list_id, count(*)
from
mail_mass_mailing_contact_list_rel r
left join mail_mass_mailing_contact c on (r.contact_id=c.id)
mailing_contact_list_rel r
left join mailing_contact c on (r.contact_id=c.id)
left join mail_blacklist bl on c.email_normalized = bl.email and bl.active
where
list_id in %s
@@ -73,30 +73,30 @@ class MassMailingList(models.Model):
# Put destination is sources lists if not already the case
src_lists |= self
self.env.cr.execute("""
INSERT INTO mail_mass_mailing_contact_list_rel (contact_id, list_id)
INSERT INTO mailing_contact_list_rel (contact_id, list_id)
SELECT st.contact_id AS contact_id, %s AS list_id
FROM
(
SELECT
contact.id AS contact_id,
contact.email AS email,
mailing_list.id AS list_id,
list.id AS list_id,
row_number() OVER (PARTITION BY email ORDER BY email) AS rn
FROM
mail_mass_mailing_contact contact,
mail_mass_mailing_contact_list_rel contact_list_rel,
mail_mass_mailing_list mailing_list
mailing_contact contact,
mailing_contact_list_rel contact_list_rel,
mailing_list list
WHERE contact.id=contact_list_rel.contact_id
AND COALESCE(contact_list_rel.opt_out,FALSE) = FALSE
AND contact.email_normalized NOT IN (select email from mail_blacklist where active = TRUE)
AND mailing_list.id=contact_list_rel.list_id
AND mailing_list.id IN %s
AND list.id=contact_list_rel.list_id
AND list.id IN %s
AND NOT EXISTS
(
SELECT 1
FROM
mail_mass_mailing_contact contact2,
mail_mass_mailing_contact_list_rel contact_list_rel2
mailing_contact contact2,
mailing_contact_list_rel contact_list_rel2
WHERE contact2.email = contact.email
AND contact_list_rel2.contact_id = contact2.id
AND contact_list_rel2.list_id = %s
+12 -12
View File
@@ -24,8 +24,8 @@ MASS_MAILING_BUSINESS_MODELS = [
'res.partner',
'event.track',
'sale.order',
'mail.mass_mailing.list',
'mail.mass_mailing.contact'
'mailing.list',
'mailing.contact'
]
# Syntax of the data URL Scheme: https://tools.ietf.org/html/rfc2397#section-3
@@ -205,7 +205,7 @@ class MassMailing(models.Model):
def default_get(self, fields):
res = super(MassMailing, self).default_get(fields)
if 'reply_to_mode' in fields and not 'reply_to_mode' in res and res.get('mailing_model_real'):
if res['mailing_model_real'] in ['res.partner', 'mail.mass_mailing.contact']:
if res['mailing_model_real'] in ['res.partner', 'mailing.contact']:
res['reply_to_mode'] = 'email'
else:
res['reply_to_mode'] = 'thread'
@@ -240,15 +240,15 @@ class MassMailing(models.Model):
reply_to = fields.Char(string='Reply To', help='Preferred Reply-To Address',
default=lambda self: self.env['mail.message']._get_default_from())
# recipients
mailing_model_real = fields.Char(compute='_compute_model', string='Recipients Real Model', default='mail.mass_mailing.contact', required=True)
mailing_model_real = fields.Char(compute='_compute_model', string='Recipients Real Model', default='mailing.contact', required=True)
mailing_model_id = fields.Many2one('ir.model', string='Recipients Model', domain=[('model', 'in', MASS_MAILING_BUSINESS_MODELS)],
default=lambda self: self.env.ref('mass_mailing.model_mail_mass_mailing_list').id)
default=lambda self: self.env.ref('mass_mailing.model_mailing_list').id)
mailing_model_name = fields.Char(related='mailing_model_id.model', string='Recipients Model Name', readonly=True, related_sudo=True)
mailing_domain = fields.Char(string='Domain', oldname='domain', default=[])
mail_server_id = fields.Many2one('ir.mail_server', string='Mail Server',
default=_get_default_mail_server_id,
help="Use a specific mail server in priority. Otherwise Odoo relies on the first outgoing mail server available (based on their sequencing) as it does for normal mails.")
contact_list_ids = fields.Many2many('mail.mass_mailing.list', 'mail_mass_mailing_list_rel',
contact_list_ids = fields.Many2many('mailing.list', 'mail_mass_mailing_list_rel',
string='Mailing Lists')
contact_ab_pc = fields.Integer(string='A/B Testing percentage',
help='Percentage of the contacts that will be mailed. Recipients will be taken randomly.', default=100)
@@ -292,7 +292,7 @@ class MassMailing(models.Model):
@api.depends('mailing_model_id')
def _compute_model(self):
for record in self:
record.mailing_model_real = (record.mailing_model_name != 'mail.mass_mailing.list') and record.mailing_model_name or 'mail.mass_mailing.contact'
record.mailing_model_real = (record.mailing_model_name != 'mailing.list') and record.mailing_model_name or 'mailing.contact'
def _compute_statistics(self):
""" Compute statistics of the mass mailing """
@@ -349,7 +349,7 @@ class MassMailing(models.Model):
def _onchange_model_and_list(self):
mailing_domain = []
if self.mailing_model_name:
if self.mailing_model_name == 'mail.mass_mailing.list':
if self.mailing_model_name == 'mailing.list':
if self.contact_list_ids:
mailing_domain.append(('list_ids', 'in', self.contact_list_ids.ids))
else:
@@ -488,9 +488,9 @@ class MassMailing(models.Model):
def update_opt_out(self, email, list_ids, value):
if len(list_ids) > 0:
model = self.env['mail.mass_mailing.contact'].with_context(active_test=False)
model = self.env['mailing.contact'].with_context(active_test=False)
records = model.search([('email_normalized', '=', tools.email_normalize(email))])
opt_out_records = self.env['mail.mass_mailing.list_contact_rel'].search([
opt_out_records = self.env['mailing.contact.subscription'].search([
('contact_id', 'in', records.ids),
('list_id', 'in', list_ids),
('opt_out', '!=', value)
@@ -514,11 +514,11 @@ class MassMailing(models.Model):
self.ensure_one()
opt_out = {}
target = self.env[self.mailing_model_real]
if self.mailing_model_real == "mail.mass_mailing.contact":
if self.mailing_model_real == "mailing.contact":
# if user is opt_out on One list but not on another
# or if two user with same email address, one opted in and the other one opted out, send the mail anyway
# TODO DBE Fixme : Optimise the following to get real opt_out and opt_in
target_list_contacts = self.env['mail.mass_mailing.list_contact_rel'].search(
target_list_contacts = self.env['mailing.contact.subscription'].search(
[('list_id', 'in', self.contact_list_ids.ids)])
opt_out_contacts = target_list_contacts.filtered(lambda rel: rel.opt_out).mapped('contact_id.email_normalized')
opt_in_contacts = target_list_contacts.filtered(lambda rel: not rel.opt_out).mapped('contact_id.email_normalized')
@@ -1,7 +1,8 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mass_mailing_tag,mail.mass_mailing.tag,model_mail_mass_mailing_tag,mass_mailing.group_mass_mailing_campaign,1,1,1,1
access_mass_mailing_contact,mail.mass_mailing.contact,model_mail_mass_mailing_contact,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mass_mailing_list,mail.mass_mailing.list,model_mail_mass_mailing_list,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mailing_contact_mm_user,access.mailing.contact.mm.user,model_mailing_contact,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mailing_contact_subscription_mm_user,access.mailing.contact.subscription.mm.user,model_mailing_contact_subscription,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mailing_list_mm_user,access.mailing.list.mm.user,model_mailing_list,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mass_mailing_stage,mail.mass_mailing.stage,model_mail_mass_mailing_stage,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mass_mailing_campaign,mail.mass_mailing.campaign,model_mail_mass_mailing_campaign,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mass_mailing_campaign_system,mail.mass_mailing.campaign.system,model_mail_mass_mailing_campaign,base.group_system,1,1,1,1
@@ -13,5 +14,4 @@ access_mailing_trace_report_mm_user,access.mailing.trace.report.mm.user,model_ma
access_utm_source,access_utm_source,utm.model_utm_source,mass_mailing.group_mass_mailing_user,1,1,1,0
access_ir_mail_server,access_ir_mail_server,base.model_ir_mail_server,mass_mailing.group_mass_mailing_user,1,0,0,0
access_mail_blacklist_mass_mailing_user,access.mail.blacklist.mass_mailing_user,mail.model_mail_blacklist,mass_mailing.group_mass_mailing_user,1,1,1,1
access_mail_mass_mailing_list_contact_rel,access.mail.mass_mailing_list_contact_rel,model_mail_mass_mailing_list_contact_rel,mass_mailing.group_mass_mailing_user,1,1,1,1
access_link_tracker_mailing,access.link.tracker.mailing,link_tracker.model_link_tracker,mass_mailing.group_mass_mailing_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mass_mailing_tag mail.mass_mailing.tag model_mail_mass_mailing_tag mass_mailing.group_mass_mailing_campaign 1 1 1 1
3 access_mass_mailing_contact access_mailing_contact_mm_user mail.mass_mailing.contact access.mailing.contact.mm.user model_mail_mass_mailing_contact model_mailing_contact mass_mailing.group_mass_mailing_user 1 1 1 1
4 access_mass_mailing_list access_mailing_contact_subscription_mm_user mail.mass_mailing.list access.mailing.contact.subscription.mm.user model_mail_mass_mailing_list model_mailing_contact_subscription mass_mailing.group_mass_mailing_user 1 1 1 1
5 access_mailing_list_mm_user access.mailing.list.mm.user model_mailing_list mass_mailing.group_mass_mailing_user 1 1 1 1
6 access_mass_mailing_stage mail.mass_mailing.stage model_mail_mass_mailing_stage mass_mailing.group_mass_mailing_user 1 1 1 1
7 access_mass_mailing_campaign mail.mass_mailing.campaign model_mail_mass_mailing_campaign mass_mailing.group_mass_mailing_user 1 1 1 1
8 access_mass_mailing_campaign_system mail.mass_mailing.campaign.system model_mail_mass_mailing_campaign base.group_system 1 1 1 1
14 access_utm_source access_utm_source utm.model_utm_source mass_mailing.group_mass_mailing_user 1 1 1 0
15 access_ir_mail_server access_ir_mail_server base.model_ir_mail_server mass_mailing.group_mass_mailing_user 1 0 0 0
16 access_mail_blacklist_mass_mailing_user access.mail.blacklist.mass_mailing_user mail.model_mail_blacklist mass_mailing.group_mass_mailing_user 1 1 1 1
access_mail_mass_mailing_list_contact_rel access.mail.mass_mailing_list_contact_rel model_mail_mass_mailing_list_contact_rel mass_mailing.group_mass_mailing_user 1 1 1 1
17 access_link_tracker_mailing access.link.tracker.mailing link_tracker.model_link_tracker mass_mailing.group_mass_mailing_user 1 1 1 1
@@ -16,7 +16,7 @@ KanbanRecord.include({
_openRecord: function () {
if (this.modelName === 'mail.mass_mailing.campaign') {
this.$('.oe_mailings').click();
} else if (this.modelName === 'mail.mass_mailing.list' &&
} else if (this.modelName === 'mailing.list' &&
this.$('.o_mailing_list_kanban_boxes a')) {
this.$('.o_mailing_list_kanban_boxes a').first().click();
} else {
@@ -9,7 +9,7 @@ class TestMassMailingCommon(common.TransactionCase):
def test_00_test_mass_mailing_list_merge(self):
# Data set up
mailing_list_A = self.env['mail.mass_mailing.list'].create({
mailing_list_A = self.env['mailing.list'].create({
'name': 'A',
'contact_ids': [
(0, 0, {'name': 'Noel Flantier', 'email': 'noel.flantier@example.com'}),
@@ -18,7 +18,7 @@ class TestMassMailingCommon(common.TransactionCase):
]
})
mailing_list_B = self.env['mail.mass_mailing.list'].create({
mailing_list_B = self.env['mailing.list'].create({
'name': 'B',
'contact_ids': [
(0, 0, {'name': 'Icallhimtest', 'email': 'icallhimtest@example.com'}),
@@ -27,7 +27,7 @@ class TestMassMailingCommon(common.TransactionCase):
]
})
mailing_list_C = self.env['mail.mass_mailing.list'].create({
mailing_list_C = self.env['mailing.list'].create({
'name': 'C',
'contact_ids': [
(0, 0, {'name': 'Norberto', 'email': 'norbert@example.com'}),
@@ -39,7 +39,7 @@ class TestMassMailingCommon(common.TransactionCase):
# This test ensure that the mailing lists are correctly merged and no
# duplicates are appearing in C
result_list = self.env['mass.mailing.list.merge'].create({
result_list = self.env['mailing.list.merge'].create({
'src_list_ids': [(4, list_id) for list_id in [mailing_list_A.id, mailing_list_B.id]],
'dest_list_id': mailing_list_C.id,
'merge_options': 'existing',
@@ -35,23 +35,23 @@ class TestMassMailingShortener(common.TransactionCase):
self.addCleanup(patcher2.stop)
def test_00_test_mass_mailing_shortener(self):
mailing_list_A = self.env['mail.mass_mailing.list'].create({
mailing_list_A = self.env['mailing.list'].create({
'name': 'A',
})
self.env['mail.mass_mailing.contact'].create({
self.env['mailing.contact'].create({
'name': 'User 1', 'email': 'user1@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
self.env['mail.mass_mailing.contact'].create({
self.env['mailing.contact'].create({
'name': 'User 2', 'email': 'user2@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
self.env['mail.mass_mailing.contact'].create({
self.env['mailing.contact'].create({
'name': 'User 3', 'email': 'user3@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
mass_mailing = self.env['mail.mass_mailing'].create({
"reply_to_mode": "email",
"reply_to": "Administrator <admin@yourcompany.example.com>",
"mailing_model_id": self.env.ref('mass_mailing.model_mail_mass_mailing_list').id,
"mailing_model_id": self.env.ref('mass_mailing.model_mailing_list').id,
"mailing_domain": "[('list_ids', 'in', [%d])]" % mailing_list_A.id,
"contact_list_ids": [[6, False, [mailing_list_A.id]]],
"mass_mailing_campaign_id": False,
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- MAILING CONTACT -->
<record model="ir.ui.view" id="mail_mass_mailing_list_contact_rel_view_form">
<!--TODO DBE : To remove - Deprecated -->
<field name="name">mail.mass_mailing.list_contact_rel.view.form</field>
<field name="model">mail.mass_mailing.list_contact_rel</field>
<!-- MAILING CONTACT SUBSCRIPTION -->
<record model="ir.ui.view" id="mailing_contact_subscription_view_form">
<field name="name">mailing.contact.subscription.view.form</field>
<field name="model">mailing.contact.subscription</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<form string="Mailing List contacts">
@@ -27,10 +26,9 @@
</field>
</record>
<record model="ir.ui.view" id="mail_mass_mailing_list_contact_rel_list_contact_view_tree">
<!--TODO DBE : To remove - Deprecated -->
<field name="name">mail.mass_mailing.list_contact_rel.list_contact.view.tree</field>
<field name="model">mail.mass_mailing.list_contact_rel</field>
<record model="ir.ui.view" id="mailing_contact_subscription_view_tree">
<field name="name">mailing.contact.subscription.view.tree</field>
<field name="model">mailing.contact.subscription</field>
<field name="arch" type="xml">
<tree string="Mailing Lists">
<field name="contact_id"/>
@@ -43,10 +41,9 @@
</field>
</record>
<record model="ir.ui.view" id="mail_mass_mailing_list_contact_view_search">
<!--TODO DBE : To remove - Deprecated -->
<field name="name">mail.mass_mailing.list_contact_rel.view.search</field>
<field name="model">mail.mass_mailing.list_contact_rel</field>
<record model="ir.ui.view" id="mailing_contact_subscription_view_search">
<field name="name">mailing.contact.subscription.view.search</field>
<field name="model">mailing.contact.subscription</field>
<field name="arch" type="xml">
<search string="Mailing List Contacts">
<field name="contact_id"/>
@@ -71,8 +68,8 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_search">
<field name="name">mail.mass_mailing.contact.search</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.search</field>
<field name="model">mailing.contact</field>
<field name="arch" type="xml">
<search string="Mailing List Contacts">
<field name="name" filter_domain="['|','|',('name','ilike',self),('company_name','ilike',self), ('email','ilike',self)]"
@@ -99,8 +96,8 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_tree">
<field name="name">mail.mass_mailing.contact.tree</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.tree</field>
<field name="model">mailing.contact</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<tree string="Mailing List Contacts">
@@ -116,8 +113,8 @@
</record>
<record id="view_mail_mass_mailing_contact_kanban" model="ir.ui.view">
<field name="name">mail.mass_mailing.contact.kanban</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.kanban</field>
<field name="model">mailing.contact</field>
<field name="arch" type="xml">
<kanban>
<field name="name"/>
@@ -158,8 +155,8 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_form">
<field name="name">mail.mass_mailing.contact.form</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.form</field>
<field name="model">mailing.contact</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<form string="Mailing List Contacts">
@@ -213,8 +210,8 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_pivot">
<field name="name">mail.mass_mailing.contact.pivot</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.pivot</field>
<field name="model">mailing.contact</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<pivot string="Mailing List Contacts" stacked="True">
@@ -224,8 +221,8 @@
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_graph">
<field name="name">mail.mass_mailing.contact.graph</field>
<field name="model">mail.mass_mailing.contact</field>
<field name="name">mailing.contact.graph</field>
<field name="model">mailing.contact</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<graph string="Mailing List Contacts" stacked="True">
@@ -236,7 +233,7 @@
<record model="ir.actions.act_window" id="action_view_mass_mailing_contacts">
<field name="name">Mailing List Contacts</field>
<field name="res_model">mail.mass_mailing.contact</field>
<field name="res_model">mailing.contact</field>
<field name="view_mode">tree,kanban,form,graph,pivot</field>
<field name="context">{'search_default_valid_recipient': 1}</field>
<field name="help" type="html">
@@ -250,7 +247,7 @@
<record model="ir.actions.act_window" id="action_view_mass_mailing_contacts_from_list">
<field name="name">Recipients</field>
<field name="res_model">mail.mass_mailing.contact</field>
<field name="res_model">mailing.contact</field>
<field name="view_mode">tree,form,graph</field>
<field name="domain">[('list_ids', 'in', [active_id])]</field>
<field name="context">{'search_default_valid_recipients': 1, 'default_list_ids': [active_id]}</field>
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- MAILING LIST -->
<record model="ir.ui.view" id="view_mail_mass_mailing_list_search">
<field name="name">mail.mass_mailing.list.search</field>
<field name="model">mail.mass_mailing.list</field>
<record model="ir.ui.view" id="mailing_list_view_search">
<field name="name">mailing.list.view.search</field>
<field name="model">mailing.list</field>
<field name="arch" type="xml">
<search string="Mailing Lists">
<field name="name"/>
@@ -18,9 +18,9 @@
</field>
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_list_tree">
<field name="name">mail.mass_mailing.list.tree</field>
<field name="model">mail.mass_mailing.list</field>
<record model="ir.ui.view" id="mailing_list_view_tree">
<field name="name">mailing.list.view.tree</field>
<field name="model">mailing.list</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<tree string="Mailing Lists">
@@ -32,9 +32,9 @@
</field>
</record>
<record model="ir.ui.view" id="view_mail_mass_mailing_list_form">
<field name="name">mail.mass_mailing.list.form</field>
<field name="model">mail.mass_mailing.list</field>
<record model="ir.ui.view" id="mailing_list_view_form">
<field name="name">mailing.list.form</field>
<field name="model">mailing.list</field>
<field name="arch" type="xml">
<form string="Contact List">
<sheet>
@@ -60,9 +60,9 @@
</field>
</record>
<record id="view_mail_mass_mailing_list_form_simplified" model="ir.ui.view">
<field name="name">mail.mass_mailing.list.form.simplified</field>
<field name="model">mail.mass_mailing.list</field>
<record id="mailing_list_view_form_simplified" model="ir.ui.view">
<field name="name">mailing.list.form.simplified</field>
<field name="model">mailing.list</field>
<field name="arch" type="xml">
<form string="Contact List">
<group>
@@ -88,15 +88,15 @@
<record id="open_create_mass_mailing_list" model="ir.actions.act_window">
<field name="name">Create a Mass Mailing List</field>
<field name="res_model">mail.mass_mailing.list</field>
<field name="res_model">mailing.list</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_mail_mass_mailing_list_form_simplified"/>
<field name="view_id" ref="mailing_list_view_form_simplified"/>
<field name="target">new</field>
</record>
<record id="view_mail_mass_mailing_list_kanban" model="ir.ui.view">
<field name="name">mail.mass_mailing.list.kanban</field>
<field name="model">mail.mass_mailing.list</field>
<record id="mailing_list_view_kanban" model="ir.ui.view">
<field name="name">mailing.list.view.kanban</field>
<field name="model">mailing.list</field>
<field name="arch" type="xml">
<kanban js_class="mass_mailing_list_kanban" class="o_kanban_mobile" on_create="mass_mailing.open_create_mass_mailing_list">
<field name="name"/>
@@ -149,7 +149,7 @@
<record model="ir.actions.act_window" id="action_view_mass_mailing_lists">
<field name="name">Mailing Lists</field>
<field name="res_model">mail.mass_mailing.list</field>
<field name="res_model">mailing.list</field>
<field name="view_mode">kanban,tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
@@ -158,10 +158,10 @@
<field name="mailing_model_name" invisible="1"/>
<field name="mailing_model_real" invisible="1"/>
<field name="mailing_domain" widget="domain"
attrs="{'invisible': [('mailing_model_name', '=', 'mail.mass_mailing.list')]}"
attrs="{'invisible': [('mailing_model_name', '=', 'mailing.list')]}"
options="{'model': 'mailing_model_real'}">
</field>
<div attrs="{'invisible': [('mailing_model_name', '!=', 'mail.mass_mailing.list')]}">
<div attrs="{'invisible': [('mailing_model_name', '!=', 'mailing.list')]}">
<label for="contact_list_ids" string="Select mailing lists:" class="oe_edit_only"/>
<field name="contact_list_ids" widget="many2many_tags"
placeholder="Select mailing lists..." class="oe_inline"/>
@@ -187,7 +187,7 @@
<label for="reply_to"/>
<div>
<field name="reply_to_mode" widget="radio"
attrs="{'invisible': [('mailing_model_name', 'in', ['mail.mass_mailing.contact', 'res.partner', 'mail.mass_mailing.list'])]}"/>
attrs="{'invisible': [('mailing_model_name', 'in', ['mailing.contact', 'res.partner', 'mailing.list'])]}"/>
<field name="reply_to"
attrs="{'required': [('reply_to_mode', '=', 'email')], 'invisible': [('reply_to_mode', '=', 'thread')]}"/>
</div>
+1 -1
View File
@@ -3,5 +3,5 @@
from . import test_mailing
from . import mail_compose_message
from . import mass_mailing_list_merge
from . import mailing_list_merge
from . import mass_mailing_schedule_date
@@ -1,18 +1,17 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, tools
from odoo.tools import email_re
class MailComposeMessage(models.TransientModel):
"""Add concept of mass mailing campaign to the mail.compose.message wizard
"""
_inherit = 'mail.compose.message'
mass_mailing_campaign_id = fields.Many2one('mail.mass_mailing.campaign', string='Mass Mailing Campaign')
mass_mailing_id = fields.Many2one('mail.mass_mailing', string='Mass Mailing', ondelete='cascade')
mass_mailing_name = fields.Char(string='Mass Mailing Name')
mailing_list_ids = fields.Many2many('mail.mass_mailing.list', string='Mailing List')
mailing_list_ids = fields.Many2many('mailing.list', string='Mailing List')
def get_mail_values(self, res_ids):
""" Override method that generated the mail content by creating the
@@ -5,11 +5,11 @@ from odoo import api, fields, models
class MassMailingListMerge(models.TransientModel):
_name = 'mass.mailing.list.merge'
_name = 'mailing.list.merge'
_description = 'Merge Mass Mailing List'
src_list_ids = fields.Many2many('mail.mass_mailing.list', string='Mailing Lists')
dest_list_id = fields.Many2one('mail.mass_mailing.list', string='Destination Mailing List')
src_list_ids = fields.Many2many('mailing.list', string='Mailing Lists')
dest_list_id = fields.Many2one('mailing.list', string='Destination Mailing List')
merge_options = fields.Selection([
('new', 'Merge into a new mailing list'),
('existing', 'Merge into an existing mailing list'),
@@ -29,7 +29,7 @@ class MassMailingListMerge(models.TransientModel):
def action_mailing_lists_merge(self):
if self.merge_options == 'new':
self.dest_list_id = self.env['mail.mass_mailing.list'].create({
self.dest_list_id = self.env['mailing.list'].create({
'name': self.new_list_name,
}).id
self.dest_list_id.action_merge(self.src_list_ids, self.archive_src_lists)
@@ -1,9 +1,9 @@
<?xml version="1.0"?>
<odoo>
<!-- Merge Mailing List -->
<record id="mass_mailing_list_merge_view_form" model="ir.ui.view">
<field name="name">mass.mailing.list.merge.form</field>
<field name="model">mass.mailing.list.merge</field>
<record id="mailing_list_merge_view_form" model="ir.ui.view">
<field name="name">mailing.list.merge.form</field>
<field name="model">mailing.list.merge</field>
<field name="arch" type="xml">
<form string="Merge Mass Mailing List">
<group>
@@ -26,8 +26,8 @@
</field>
</record>
<act_window id="mass_mailing_list_merge_action" name="Merge Selected Mailing Lists"
res_model="mass.mailing.list.merge"
binding_model="mail.mass_mailing.list" binding_views="list"
<act_window id="mailing_list_merge_action" name="Merge Selected Mailing Lists"
res_model="mailing.list.merge"
binding_model="mailing.list" binding_views="list"
view_mode="form" target="new"/>
</odoo>
@@ -6,7 +6,7 @@ import datetime
class TestAutoBlacklist(common.TransactionCase):
def test_mail_bounced_auto_blacklist(self):
mass_mailing_contacts = self.env['mail.mass_mailing.contact']
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing = self.env['mail.mass_mailing']
mail_blacklist = self.env['mail.blacklist']
mail_statistics = self.env['mailing.trace']
@@ -17,28 +17,28 @@ class TestAutoBlacklist(common.TransactionCase):
# create bounced history
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=2),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=3),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=4),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=5),
'email': self.mailing_contact_1.email
@@ -70,7 +70,7 @@ class TestAutoBlacklist(common.TransactionCase):
composer.send_mail()
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now(),
'email': self.mailing_contact_1.email
@@ -68,7 +68,7 @@ class TestMassMail(MassMailingCase):
class TestAccessRights(TransactionCase):
def test_01_mass_mail_blacklist(self):
mass_mailing_contacts = self.env['mail.mass_mailing.contact']
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing = self.env['mail.mass_mailing']
mail_blacklist = self.env['mail.blacklist']
@@ -110,9 +110,9 @@ class TestAccessRights(TransactionCase):
'blacklist ignored email number incorrect, should be equals to 2')
def test_02_mass_mail_simple_opt_out(self):
mass_mailing_contacts = self.env['mail.mass_mailing.contact']
mass_mailing_lists = self.env['mail.mass_mailing.list']
mass_mailing_optout = self.env['mail.mass_mailing.list_contact_rel']
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mail.mass_mailing']
# create mailing contact record
@@ -159,9 +159,9 @@ class TestAccessRights(TransactionCase):
'Opt Out ignored email number incorrect, should be equals to 1')
def test_03_mass_mail_multi_opt_out(self):
mass_mailing_contacts = self.env['mail.mass_mailing.contact']
mass_mailing_lists = self.env['mail.mass_mailing.list']
mass_mailing_optout = self.env['mail.mass_mailing.list_contact_rel']
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mail.mass_mailing']
# create mailing contact record
@@ -216,9 +216,9 @@ class TestAccessRights(TransactionCase):
'Opt Out ignored email number incorrect, should be equals to 0')
def test_04_mass_mail_multi_users_different_opt_out(self):
mass_mailing_contacts = self.env['mail.mass_mailing.contact']
mass_mailing_lists = self.env['mail.mass_mailing.list']
mass_mailing_optout = self.env['mail.mass_mailing.list_contact_rel']
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mail.mass_mailing']
# create mailing contact record
+2 -1
View File
@@ -15,7 +15,8 @@ On a simple click, your visitors can subscribe to mailing lists managed in the E
'security/ir.model.access.csv',
'views/website_mass_mailing_templates.xml',
'views/snippets_templates.xml',
'views/mass_mailing_view.xml',
'views/mailing_list_views.xml',
'views/website_mass_mailing_views.xml',
],
'qweb': [
'static/src/xml/*.xml',
@@ -18,29 +18,29 @@ class MassMailController(MassMailController):
is_subscriber = False
if email:
contacts_count = request.env['mail.mass_mailing.list_contact_rel'].sudo().search_count([('list_id', 'in', [int(list_id)]), ('contact_id.email', '=', email), ('opt_out', '=', False)])
contacts_count = request.env['mailing.contact.subscription'].sudo().search_count([('list_id', 'in', [int(list_id)]), ('contact_id.email', '=', email), ('opt_out', '=', False)])
is_subscriber = contacts_count > 0
return {'is_subscriber': is_subscriber, 'email': email}
@route('/website_mass_mailing/subscribe', type='json', website=True, auth="public")
def subscribe(self, list_id, email, **post):
List_contact_rel = request.env['mail.mass_mailing.list_contact_rel'].sudo()
Contacts = request.env['mail.mass_mailing.contact'].sudo()
ContactSubscription = request.env['mailing.contact.subscription'].sudo()
Contacts = request.env['mailing.contact'].sudo()
name, email = Contacts.get_name_email(email)
list_contact_rel = List_contact_rel.search([('list_id', '=', int(list_id)), ('contact_id.email', '=', email)], limit=1)
if not list_contact_rel:
subscription = ContactSubscription.search([('list_id', '=', int(list_id)), ('contact_id.email', '=', email)], limit=1)
if not subscription:
# inline add_to_list as we've already called half of it
contact_id = Contacts.search([('email', '=', email)], limit=1)
if not contact_id:
contact_id = Contacts.create({'name': name, 'email': email})
List_contact_rel.create({'contact_id': contact_id.id, 'list_id': int(list_id)})
elif list_contact_rel.opt_out:
list_contact_rel.opt_out = False
ContactSubscription.create({'contact_id': contact_id.id, 'list_id': int(list_id)})
elif subscription.opt_out:
subscription.opt_out = False
# add email to session
request.session['mass_mailing_email'] = email
mass_mailing_list = request.env['mail.mass_mailing.list'].sudo().browse(list_id)
mass_mailing_list = request.env['mailing.list'].sudo().browse(list_id)
return {'toast_content': mass_mailing_list.toast_content}
@route(['/website_mass_mailing/get_content'], type='json', website=True, auth="public")
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mass_mailing_list
from . import mailing_list
from . import website_mass_mailing
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class MailingList(models.Model):
_inherit = 'mailing.list'
def _default_toast_content(self):
return '<p>Thanks for subscribing!</p>'
website_popup_ids = fields.One2many('website.mass_mailing.popup', 'mailing_list_id', string="Website Popups")
toast_content = fields.Html(default=_default_toast_content, translate=True)
@@ -4,16 +4,6 @@
from odoo import fields, models
class MassMailingList(models.Model):
_inherit = 'mail.mass_mailing.list'
def _default_toast_content(self):
return '<p>Thanks for subscribing!</p>'
website_popup_ids = fields.One2many('website.mass_mailing.popup', 'mailing_list_id', string="Website Popups")
toast_content = fields.Html(default=_default_toast_content, translate=True)
class MassMailingPopup(models.Model):
_name = 'website.mass_mailing.popup'
_description = "Mailing list popup"
@@ -21,6 +11,6 @@ class MassMailingPopup(models.Model):
def _default_popup_content(self):
return self.env['ir.ui.view'].render_template('website_mass_mailing.s_newsletter_block')
mailing_list_id = fields.Many2one('mail.mass_mailing.list')
mailing_list_id = fields.Many2one('mailing.list')
website_id = fields.Many2one('website')
popup_content = fields.Html(string="Website Popup Content", default=_default_popup_content, translate=True, sanitize=False)
@@ -30,7 +30,7 @@ options.registry.mailing_list_subscribe = options.Class.extend({
'select': _t("Newsletter"),
'init': function (field, dialog) {
return rpc.query({
model: 'mail.mass_mailing.list',
model: 'mailing.list',
method: 'name_search',
args: ['', [['is_public', '=', true]]],
context: self.options.recordInfo.context,
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mailing_list_view_form" model="ir.ui.view">
<field name="name">mailing.list.view.form.inherit.website</field>
<field name="model">mailing.list</field>
<field name="inherit_id" ref="mass_mailing.mailing_list_view_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="inside">
<notebook>
<page string="Website popups">
<field name="website_popup_ids">
<tree>
<field name="website_id"/>
</tree>
</field>
</page>
</notebook>
</xpath>
<xpath expr="//div[hasclass('oe_title')]" position="after">
<group>
<field name="toast_content"/>
</group>
</xpath>
</field>
</record>
</odoo>
@@ -1,29 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_mail_mass_mailing_list_form" model="ir.ui.view">
<field name="name">mail.mass_mailing.list.form</field>
<field name="model">mail.mass_mailing.list</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_list_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="inside">
<notebook>
<page string="Website popups">
<field name="website_popup_ids">
<tree>
<field name="website_id"/>
</tree>
</field>
</page>
</notebook>
</xpath>
<xpath expr="//div[hasclass('oe_title')]" position="after">
<group>
<field name="toast_content"/>
</group>
</xpath>
</field>
</record>
<record id="view_mail_mass_mailing_popup_form" model="ir.ui.view">
<field name="name">website.mass_mailing.popup.form</field>
<field name="model">website.mass_mailing.popup</field>