PURPOSE Reorganize addon according to guidelines, helping finding and updating code. SPECIFICATIONS Move subscription model into its own file, to ease future improvements. Do the same for its views. Also move menu entries into a specific file for menus, allowing to easily understand menu organization in mass mailing. A duplicated menu about link trackers in SMS is also removed. Task-2864264 (Mass Mailing Module Reorganization) Part-of: odoo/odoo#92509
163 lines
7.3 KiB
Python
163 lines
7.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import UserError
|
|
from odoo.osv import expression
|
|
|
|
|
|
class MassMailingContact(models.Model):
|
|
"""Model of a contact. This model is different from the partner 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 = 'mailing.contact'
|
|
_inherit = ['mail.thread.blacklist']
|
|
_description = 'Mailing Contact'
|
|
_order = 'email'
|
|
_mailing_enabled = True
|
|
|
|
def default_get(self, fields_list):
|
|
""" When coming from a mailing list we may have a default_list_ids context
|
|
key. We should use it to create subscription_list_ids default value that
|
|
are displayed to the user as list_ids is not displayed on form view. """
|
|
res = super(MassMailingContact, self).default_get(fields_list)
|
|
if 'subscription_list_ids' in fields_list and not res.get('subscription_list_ids'):
|
|
list_ids = self.env.context.get('default_list_ids')
|
|
if 'default_list_ids' not in res and list_ids and isinstance(list_ids, (list, tuple)):
|
|
res['subscription_list_ids'] = [
|
|
(0, 0, {'list_id': list_id}) for list_id in list_ids]
|
|
return res
|
|
|
|
name = fields.Char()
|
|
company_name = fields.Char(string='Company Name')
|
|
title_id = fields.Many2one('res.partner.title', string='Title')
|
|
email = fields.Char('Email')
|
|
list_ids = fields.Many2many(
|
|
'mailing.list', 'mailing_contact_list_rel',
|
|
'contact_id', 'list_id', string='Mailing Lists')
|
|
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',
|
|
help='Opt out flag for a specific mailing list. '
|
|
'This field should not be used in a view without a unique and active mailing list context.')
|
|
|
|
@api.model
|
|
def _search_opt_out(self, operator, value):
|
|
# Assumes operator is '=' or '!=' and value is True or False
|
|
if operator != '=':
|
|
if operator == '!=' and isinstance(value, bool):
|
|
value = not value
|
|
else:
|
|
raise NotImplementedError()
|
|
|
|
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['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])]
|
|
return expression.FALSE_DOMAIN if value else expression.TRUE_DOMAIN
|
|
|
|
@api.depends('subscription_list_ids')
|
|
@api.depends_context('default_list_ids')
|
|
def _compute_opt_out(self):
|
|
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']
|
|
for record in self:
|
|
active_subscription_list = record.subscription_list_ids.filtered(lambda l: l.list_id.id == active_list_id)
|
|
record.opt_out = active_subscription_list.opt_out
|
|
else:
|
|
for record in self:
|
|
record.opt_out = False
|
|
|
|
def get_name_email(self, name):
|
|
name, email = self.env['res.partner']._parse_partner_name(name)
|
|
if name and not email:
|
|
email = name
|
|
if email and not name:
|
|
name = email
|
|
return name, email
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
""" Synchronize default_list_ids (currently used notably for computed
|
|
fields) default key with subscription_list_ids given by user when creating
|
|
contacts.
|
|
|
|
Those two values have the same purpose, adding a list to to the contact
|
|
either through a direct write on m2m, either through a write on middle
|
|
model subscription.
|
|
|
|
This is a bit hackish but is due to default_list_ids key being
|
|
used to compute oupt_out field. This should be cleaned in master but here
|
|
we simply try to limit issues while keeping current behavior. """
|
|
default_list_ids = self._context.get('default_list_ids')
|
|
default_list_ids = default_list_ids if isinstance(default_list_ids, (list, tuple)) else []
|
|
|
|
for vals in vals_list:
|
|
if vals.get('list_ids') and vals.get('subscription_list_ids'):
|
|
raise UserError(_('You should give either list_ids, either subscription_list_ids to create new contacts.'))
|
|
|
|
if default_list_ids:
|
|
for vals in vals_list:
|
|
if vals.get('list_ids'):
|
|
continue
|
|
current_list_ids = []
|
|
subscription_ids = vals.get('subscription_list_ids') or []
|
|
for subscription in subscription_ids:
|
|
if len(subscription) == 3:
|
|
current_list_ids.append(subscription[2]['list_id'])
|
|
for list_id in set(default_list_ids) - set(current_list_ids):
|
|
subscription_ids.append((0, 0, {'list_id': list_id}))
|
|
vals['subscription_list_ids'] = subscription_ids
|
|
|
|
return super(MassMailingContact, self.with_context(default_list_ids=False)).create(vals_list)
|
|
|
|
@api.returns('self', lambda value: value.id)
|
|
def copy(self, default=None):
|
|
""" Cleans the default_list_ids while duplicating mailing contact in context of
|
|
a mailing list because we already have subscription lists copied over for newly
|
|
created contact, no need to add the ones from default_list_ids again """
|
|
if self.env.context.get('default_list_ids'):
|
|
self = self.with_context(default_list_ids=False)
|
|
return super().copy(default)
|
|
|
|
@api.model
|
|
def name_create(self, name):
|
|
name, email = self.get_name_email(name)
|
|
contact = self.create({'name': name, 'email': email})
|
|
return contact.name_get()[0]
|
|
|
|
@api.model
|
|
def add_to_list(self, name, list_id):
|
|
name, email = self.get_name_email(name)
|
|
contact = self.create({'name': name, 'email': email, 'list_ids': [(4, list_id)]})
|
|
return contact.name_get()[0]
|
|
|
|
def _message_get_default_recipients(self):
|
|
return {r.id: {
|
|
'partner_ids': [],
|
|
'email_to': r.email_normalized,
|
|
'email_cc': False}
|
|
for r in self
|
|
}
|
|
|
|
def action_add_to_mailing_list(self):
|
|
ctx = dict(self.env.context, default_contact_ids=self.ids)
|
|
action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.mailing_contact_to_list_action")
|
|
action['view_mode'] = 'form'
|
|
action['target'] = 'new'
|
|
action['context'] = ctx
|
|
|
|
return action
|
|
|
|
@api.model
|
|
def get_import_templates(self):
|
|
return [{
|
|
'label': _('Import Template for Mailing List Contacts'),
|
|
'template': '/mass_mailing/static/xls/mailing_contact.xls'
|
|
}]
|