diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/mass_mailing/models/mailing_contact.py | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/mass_mailing/models/mailing_contact.py')
| -rw-r--r-- | addons/mass_mailing/models/mailing_contact.py | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/addons/mass_mailing/models/mailing_contact.py b/addons/mass_mailing/models/mailing_contact.py new file mode 100644 index 00000000..27ce87a2 --- /dev/null +++ b/addons/mass_mailing/models/mailing_contact.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models +from odoo.osv import expression + + +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 = 'mailing.contact.subscription' + _description = 'Mass Mailing Subscription Information' + _table = 'mailing_contact_list_rel' + _rec_name = 'contact_id' + + 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') + message_bounce = fields.Integer(related='contact_id.message_bounce', store=False, readonly=False) + is_blacklisted = fields.Boolean(related='contact_id.is_blacklisted', store=False, readonly=False) + + _sql_constraints = [ + ('unique_contact_list', 'unique (contact_id, list_id)', + 'A mailing contact cannot subscribe to the same mailing list multiple times.') + ] + + @api.model + def create(self, vals): + if 'opt_out' in vals: + vals['unsubscription_date'] = vals['opt_out'] and fields.Datetime.now() + return super(MassMailingContactListRel, self).create(vals) + + def write(self, vals): + if 'opt_out' in vals: + vals['unsubscription_date'] = vals['opt_out'] and fields.Datetime.now() + return super(MassMailingContactListRel, self).write(vals) + + +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' + + def default_get(self, fields): + """ 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) + if 'subscription_list_ids' in fields 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])] + else: + 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 [] + + if default_list_ids: + for vals in vals_list: + 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 + } |
