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_sms/models | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/mass_mailing_sms/models')
| -rw-r--r-- | addons/mass_mailing_sms/models/__init__.py | 10 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/mailing_contact.py | 15 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/mailing_list.py | 36 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/mailing_mailing.py | 279 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/mailing_trace.py | 87 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/res_users.py | 72 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/sms_sms.py | 44 | ||||
| -rw-r--r-- | addons/mass_mailing_sms/models/utm.py | 42 |
8 files changed, 585 insertions, 0 deletions
diff --git a/addons/mass_mailing_sms/models/__init__.py b/addons/mass_mailing_sms/models/__init__.py new file mode 100644 index 00000000..1f0a7eb2 --- /dev/null +++ b/addons/mass_mailing_sms/models/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import mailing_contact +from . import mailing_list +from . import mailing_mailing +from . import mailing_trace +from . import res_users +from . import sms_sms +from . import utm diff --git a/addons/mass_mailing_sms/models/mailing_contact.py b/addons/mass_mailing_sms/models/mailing_contact.py new file mode 100644 index 00000000..73a3431e --- /dev/null +++ b/addons/mass_mailing_sms/models/mailing_contact.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class MailingContact(models.Model): + _name = 'mailing.contact' + _inherit = ['mailing.contact', 'mail.thread.phone'] + + mobile = fields.Char(string='Mobile') + + def _sms_get_number_fields(self): + # TDE note: should override _phone_get_number_fields but ok as sms is in dependencies + return ['mobile'] diff --git a/addons/mass_mailing_sms/models/mailing_list.py b/addons/mass_mailing_sms/models/mailing_list.py new file mode 100644 index 00000000..9e48fa7d --- /dev/null +++ b/addons/mass_mailing_sms/models/mailing_list.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class MailingList(models.Model): + _inherit = 'mailing.list' + + def _compute_contact_nbr(self): + if self.env.context.get('mailing_sms') and self.ids: + self.env.cr.execute(''' +select list_id, count(*) +from mailing_contact_list_rel r +left join mailing_contact c on (r.contact_id=c.id) +left join phone_blacklist bl on c.phone_sanitized = bl.number and bl.active +where + list_id in %s + AND COALESCE(r.opt_out,FALSE) = FALSE + AND c.phone_sanitized IS NOT NULL + AND bl.id IS NULL +group by list_id''', (tuple(self.ids), )) + data = dict(self.env.cr.fetchall()) + for mailing_list in self: + mailing_list.contact_nbr = data.get(mailing_list.id, 0) + return + return super(MailingList, self)._compute_contact_nbr() + + def action_view_contacts(self): + if self.env.context.get('mailing_sms'): + action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing_sms.mailing_contact_action_sms") + action['domain'] = [('list_ids', 'in', self.ids)] + context = dict(self.env.context, search_default_filter_valid_sms_recipient=1, default_list_ids=self.ids) + action['context'] = context + return action + return super(MailingList, self).action_view_contacts() diff --git a/addons/mass_mailing_sms/models/mailing_mailing.py b/addons/mass_mailing_sms/models/mailing_mailing.py new file mode 100644 index 00000000..ea2e36d7 --- /dev/null +++ b/addons/mass_mailing_sms/models/mailing_mailing.py @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.osv import expression + +_logger = logging.getLogger(__name__) + + +class Mailing(models.Model): + _inherit = 'mailing.mailing' + + @api.model + def default_get(self, fields): + res = super(Mailing, self).default_get(fields) + if fields is not None and 'keep_archives' in fields and res.get('mailing_type') == 'sms': + res['keep_archives'] = True + return res + + # mailing options + mailing_type = fields.Selection(selection_add=[ + ('sms', 'SMS') + ], ondelete={'sms': 'set default'}) + + # 'sms_subject' added to override 'subject' field (string attribute should be labelled "Title" when mailing_type == 'sms'). + # 'sms_subject' should have the same helper as 'subject' field when 'mass_mailing_sms' installed. + # otherwise 'sms_subject' will get the old helper from 'mass_mailing' module. + # overriding 'subject' field helper in this model is not working, since the helper will keep the new value + # even when 'mass_mailing_sms' removed (see 'mailing_mailing_view_form_sms' for more details). + sms_subject = fields.Char('Title', help='For an email, the subject your recipients will see in their inbox.\n' + 'For an SMS, the internal title of the message.', + related='subject', translate=True, readonly=False) + # sms options + body_plaintext = fields.Text('SMS Body', compute='_compute_body_plaintext', store=True, readonly=False) + sms_template_id = fields.Many2one('sms.template', string='SMS Template', ondelete='set null') + sms_has_insufficient_credit = fields.Boolean( + 'Insufficient IAP credits', compute='_compute_sms_has_iap_failure', + help='UX Field to propose to buy IAP credits') + sms_has_unregistered_account = fields.Boolean( + 'Unregistered IAP account', compute='_compute_sms_has_iap_failure', + help='UX Field to propose to Register the SMS IAP account') + sms_force_send = fields.Boolean( + 'Send Directly', help='Use at your own risks.') + # opt_out_link + sms_allow_unsubscribe = fields.Boolean('Include opt-out link', default=False) + + @api.depends('mailing_type') + def _compute_medium_id(self): + super(Mailing, self)._compute_medium_id() + for mailing in self: + if mailing.mailing_type == 'sms' and (not mailing.medium_id or mailing.medium_id == self.env.ref('utm.utm_medium_email')): + mailing.medium_id = self.env.ref('mass_mailing_sms.utm_medium_sms').id + elif mailing.mailing_type == 'mail' and (not mailing.medium_id or mailing.medium_id == self.env.ref('mass_mailing_sms.utm_medium_sms')): + mailing.medium_id = self.env.ref('utm.utm_medium_email').id + + @api.depends('sms_template_id', 'mailing_type') + def _compute_body_plaintext(self): + for mailing in self: + if mailing.mailing_type == 'sms' and mailing.sms_template_id: + mailing.body_plaintext = mailing.sms_template_id.body + + @api.depends('mailing_trace_ids.failure_type') + def _compute_sms_has_iap_failure(self): + failures = ['sms_acc', 'sms_credit'] + if not self.ids: + self.sms_has_insufficient_credit = self.sms_has_unregistered_account = False + else: + traces = self.env['mailing.trace'].sudo().read_group([ + ('mass_mailing_id', 'in', self.ids), + ('trace_type', '=', 'sms'), + ('failure_type', 'in', failures) + ], ['mass_mailing_id', 'failure_type'], ['mass_mailing_id', 'failure_type'], lazy=False) + + trace_dict = dict.fromkeys(self.ids, {key: False for key in failures}) + for t in traces: + trace_dict[t['mass_mailing_id'][0]][t['failure_type']] = t['__count'] and True or False + + for mail in self: + mail.sms_has_insufficient_credit = trace_dict[mail.id]['sms_credit'] + mail.sms_has_unregistered_account = trace_dict[mail.id]['sms_acc'] + + + # -------------------------------------------------- + # ORM OVERRIDES + # -------------------------------------------------- + + @api.model + def create(self, values): + # Get subject from "sms_subject" field when SMS installed (used to build the name of record in the super 'create' method) + if values.get('mailing_type') == 'sms' and values.get('sms_subject'): + values['subject'] = values['sms_subject'] + return super(Mailing, self).create(values) + + # -------------------------------------------------- + # BUSINESS / VIEWS ACTIONS + # -------------------------------------------------- + + def action_put_in_queue_sms(self): + res = self.action_put_in_queue() + if self.sms_force_send: + self.action_send_mail() + return res + + def action_send_now_sms(self): + if not self.sms_force_send: + self.write({'sms_force_send': True}) + return self.action_send_mail() + + def action_retry_failed(self): + mass_sms = self.filtered(lambda m: m.mailing_type == 'sms') + if mass_sms: + mass_sms.action_retry_failed_sms() + return super(Mailing, self - mass_sms).action_retry_failed() + + def action_retry_failed_sms(self): + failed_sms = self.env['sms.sms'].sudo().search([ + ('mailing_id', 'in', self.ids), + ('state', '=', 'error') + ]) + failed_sms.mapped('mailing_trace_ids').unlink() + failed_sms.unlink() + self.write({'state': 'in_queue'}) + + def action_test(self): + if self.mailing_type == 'sms': + ctx = dict(self.env.context, default_mailing_id=self.id) + return { + 'name': _('Test SMS marketing'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'mailing.sms.test', + 'target': 'new', + 'context': ctx, + } + return super(Mailing, self).action_test() + + def _action_view_traces_filtered(self, view_filter): + action = super(Mailing, self)._action_view_traces_filtered(view_filter) + if self.mailing_type == 'sms': + action['views'] = [(self.env.ref('mass_mailing_sms.mailing_trace_view_tree_sms').id, 'tree'), + (self.env.ref('mass_mailing_sms.mailing_trace_view_form_sms').id, 'form')] + return action + + def action_buy_sms_credits(self): + url = self.env['iap.account'].get_credits_url(service_name='sms') + return { + 'type': 'ir.actions.act_url', + 'url': url, + } + + # -------------------------------------------------- + # SMS SEND + # -------------------------------------------------- + + def _get_opt_out_list_sms(self): + """Returns a set of emails opted-out in target model""" + self.ensure_one() + opt_out = [] + target = self.env[self.mailing_model_real] + 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 + subscriptions = self.env['mailing.contact.subscription'].sudo().search( + [('list_id', 'in', self.contact_list_ids.ids)]) + opt_out_contacts = subscriptions.filtered(lambda sub: sub.opt_out).mapped('contact_id') + opt_in_contacts = subscriptions.filtered(lambda sub: not sub.opt_out).mapped('contact_id') + opt_out = list(set(c.id for c in opt_out_contacts if c not in opt_in_contacts)) + + _logger.info("Mass SMS %s targets %s: optout: %s contacts", self, target._name, len(opt_out)) + else: + _logger.info("Mass SMS %s targets %s: no opt out list available", self, target._name) + return opt_out + + def _get_seen_list_sms(self): + """Returns a set of emails already targeted by current mailing/campaign (no duplicates)""" + self.ensure_one() + target = self.env[self.mailing_model_real] + + partner_fields = [] + if issubclass(type(target), self.pool['mail.thread.phone']): + phone_fields = ['phone_sanitized'] + elif issubclass(type(target), self.pool['mail.thread']): + phone_fields = target._sms_get_number_fields() + partner_fields = target._sms_get_partner_fields() + else: + phone_fields = [] + if 'mobile' in target._fields: + phone_fields.append('mobile') + if 'phone' in target._fields: + phone_fields.append('phone') + partner_field = next( + (fname for fname in partner_fields if target._fields[fname].type == 'many2one'), + False + ) + if not phone_fields and not partner_field: + raise UserError(_("Unsupported %s for mass SMS", self.mailing_model_id.name)) + + query = """ + SELECT %(select_query)s + FROM mailing_trace trace + JOIN %(target_table)s target ON (trace.res_id = target.id) + %(join_add_query)s + WHERE (%(where_query)s) + AND trace.mass_mailing_id = %%(mailing_id)s + AND trace.model = %%(target_model)s + """ + if phone_fields: + # phone fields are checked on target mailed model + select_query = 'target.id, ' + ', '.join('target.%s' % fname for fname in phone_fields) + where_query = ' OR '.join('target.%s IS NOT NULL' % fname for fname in phone_fields) + join_add_query = '' + else: + # phone fields are checked on res.partner model + partner_phone_fields = ['mobile', 'phone'] + select_query = 'target.id, ' + ', '.join('partner.%s' % fname for fname in partner_phone_fields) + where_query = ' OR '.join('partner.%s IS NOT NULL' % fname for fname in partner_phone_fields) + join_add_query = 'JOIN res_partner partner ON (target.%s = partner.id)' % partner_field + + query = query % { + 'select_query': select_query, + 'where_query': where_query, + 'target_table': target._table, + 'join_add_query': join_add_query, + } + params = {'mailing_id': self.id, 'target_model': self.mailing_model_real} + self._cr.execute(query, params) + query_res = self._cr.fetchall() + seen_list = set(number for item in query_res for number in item[1:] if number) + seen_ids = set(item[0] for item in query_res) + _logger.info("Mass SMS %s targets %s: already reached %s SMS", self, target._name, len(seen_list)) + return list(seen_ids), list(seen_list) + + def _send_sms_get_composer_values(self, res_ids): + return { + # content + 'body': self.body_plaintext, + 'template_id': self.sms_template_id.id, + 'res_model': self.mailing_model_real, + 'res_ids': repr(res_ids), + # options + 'composition_mode': 'mass', + 'mailing_id': self.id, + 'mass_keep_log': self.keep_archives, + 'mass_force_send': self.sms_force_send, + 'mass_sms_allow_unsubscribe': self.sms_allow_unsubscribe, + } + + def action_send_mail(self, res_ids=None): + mass_sms = self.filtered(lambda m: m.mailing_type == 'sms') + if mass_sms: + mass_sms.action_send_sms(res_ids=res_ids) + return super(Mailing, self - mass_sms).action_send_mail(res_ids=res_ids) + + def action_send_sms(self, res_ids=None): + for mailing in self: + if not res_ids: + res_ids = mailing._get_remaining_recipients() + if not res_ids: + raise UserError(_('There are no recipients selected.')) + + composer = self.env['sms.composer'].with_context(active_id=False).create(mailing._send_sms_get_composer_values(res_ids)) + composer._action_send_sms() + mailing.write({'state': 'done', 'sent_date': fields.Datetime.now()}) + return True + + # -------------------------------------------------- + # TOOLS + # -------------------------------------------------- + + def _get_default_mailing_domain(self): + mailing_domain = super(Mailing, self)._get_default_mailing_domain() + if self.mailing_type == 'sms' and 'phone_sanitized_blacklisted' in self.env[self.mailing_model_name]._fields: + mailing_domain = expression.AND([mailing_domain, [('phone_sanitized_blacklisted', '=', False)]]) + + return mailing_domain diff --git a/addons/mass_mailing_sms/models/mailing_trace.py b/addons/mass_mailing_sms/models/mailing_trace.py new file mode 100644 index 00000000..743afe14 --- /dev/null +++ b/addons/mass_mailing_sms/models/mailing_trace.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import random +import string + +from odoo import api, fields, models +from odoo.osv import expression + + +class MailingTrace(models.Model): + """ Improve statistics model to add SMS support. Main attributes of + statistics model are used, only some specific data is required. """ + _inherit = 'mailing.trace' + CODE_SIZE = 3 + + trace_type = fields.Selection(selection_add=[ + ('sms', 'SMS') + ], ondelete={'sms': 'set default'}) + sms_sms_id = fields.Many2one('sms.sms', string='SMS', index=True, ondelete='set null') + sms_sms_id_int = fields.Integer( + string='SMS ID (tech)', + help='ID of the related sms.sms. This field is an integer field because ' + 'the related sms.sms can be deleted separately from its statistics. ' + 'However the ID is needed for several action and controllers.', + index=True, + ) + sms_number = fields.Char('Number') + sms_code = fields.Char('Code') + failure_type = fields.Selection(selection_add=[ + ('sms_number_missing', 'Missing Number'), + ('sms_number_format', 'Wrong Number Format'), + ('sms_credit', 'Insufficient Credit'), + ('sms_server', 'Server Error'), + ('sms_acc', 'Unregistered Account'), + # mass mode specific codes + ('sms_blacklist', 'Blacklisted'), + ('sms_duplicate', 'Duplicate'), + ]) + + @api.model_create_multi + def create(self, values_list): + for values in values_list: + if 'sms_sms_id' in values: + values['sms_sms_id_int'] = values['sms_sms_id'] + if values.get('trace_type') == 'sms' and not values.get('sms_code'): + values['sms_code'] = self._get_random_code() + return super(MailingTrace, self).create(values_list) + + def _get_random_code(self): + """ Generate a random code for trace. Uniqueness is not really necessary + as it serves as obfuscation when unsubscribing. A valid trio + code / mailing_id / number will be requested. """ + return ''.join(random.choice(string.ascii_letters + string.digits) for dummy in range(self.CODE_SIZE)) + + def _get_records_from_sms(self, sms_sms_ids=None, additional_domain=None): + if not self.ids and sms_sms_ids: + domain = [('sms_sms_id_int', 'in', sms_sms_ids)] + else: + domain = [('id', 'in', self.ids)] + if additional_domain: + domain = expression.AND([domain, additional_domain]) + return self.search(domain) + + def set_failed(self, failure_type): + for trace in self: + trace.write({'exception': fields.Datetime.now(), 'failure_type': failure_type}) + + def set_sms_sent(self, sms_sms_ids=None): + statistics = self._get_records_from_sms(sms_sms_ids, [('sent', '=', False)]) + statistics.write({'sent': fields.Datetime.now()}) + return statistics + + def set_sms_clicked(self, sms_sms_ids=None): + statistics = self._get_records_from_sms(sms_sms_ids, [('clicked', '=', False)]) + statistics.write({'clicked': fields.Datetime.now()}) + return statistics + + def set_sms_ignored(self, sms_sms_ids=None): + statistics = self._get_records_from_sms(sms_sms_ids, [('ignored', '=', False)]) + statistics.write({'ignored': fields.Datetime.now()}) + return statistics + + def set_sms_exception(self, sms_sms_ids=None): + statistics = self._get_records_from_sms(sms_sms_ids, [('exception', '=', False)]) + statistics.write({'exception': fields.Datetime.now()}) + return statistics diff --git a/addons/mass_mailing_sms/models/res_users.py b/addons/mass_mailing_sms/models/res_users.py new file mode 100644 index 00000000..8c23887c --- /dev/null +++ b/addons/mass_mailing_sms/models/res_users.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import json + +from odoo import api, fields, models, modules, _ + + +class Users(models.Model): + _name = 'res.users' + _inherit = ['res.users'] + + @api.model + def systray_get_activities(self): + """ Split mass_mailing and mass_mailing_sms activities in systray by + removing the single mailing.mailing activity represented and + doing a new query to split them by mailing_type. + """ + activities = super(Users, self).systray_get_activities() + for activity in activities: + if activity.get('model') == 'mailing.mailing': + activities.remove(activity) + query = """SELECT m.mailing_type, count(*), act.res_model as model, act.res_id, + CASE + WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today' + WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue' + WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned' + END AS states + FROM mail_activity AS act + JOIN mailing_mailing AS m ON act.res_id = m.id + WHERE act.res_model = 'mailing.mailing' AND act.user_id = %(user_id)s + GROUP BY m.mailing_type, states, act.res_model, act.res_id; + """ + self.env.cr.execute(query, { + 'today': fields.Date.context_today(self), + 'user_id': self.env.uid, + }) + activity_data = self.env.cr.dictfetchall() + + user_activities = {} + for act in activity_data: + if not user_activities.get(act['mailing_type']): + if act['mailing_type'] == 'sms': + module = 'mass_mailing_sms' + name = _('SMS Marketing') + else: + module = 'mass_mailing' + name = _('Email Marketing') + icon = module and modules.module.get_module_icon(module) + res_ids = set() + user_activities[act['mailing_type']] = { + 'name': name, + 'model': 'mailing.mailing', + 'type': 'activity', + 'icon': icon, + 'total_count': 0, 'today_count': 0, 'overdue_count': 0, 'planned_count': 0, + 'res_ids': res_ids, + } + user_activities[act['mailing_type']]['res_ids'].add(act['res_id']) + user_activities[act['mailing_type']]['%s_count' % act['states']] += act['count'] + if act['states'] in ('today', 'overdue'): + user_activities[act['mailing_type']]['total_count'] += act['count'] + + for mailing_type in user_activities.keys(): + user_activities[mailing_type].update({ + 'actions': [{'icon': 'fa-clock-o', 'name': 'Summary',}], + 'domain': json.dumps([['activity_ids.res_id', 'in', list(user_activities[mailing_type]['res_ids'])]]) + }) + activities.extend(list(user_activities.values())) + break + + return activities diff --git a/addons/mass_mailing_sms/models/sms_sms.py b/addons/mass_mailing_sms/models/sms_sms.py new file mode 100644 index 00000000..c9c14e14 --- /dev/null +++ b/addons/mass_mailing_sms/models/sms_sms.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import re + +from odoo import fields, models, tools + + +class SmsSms(models.Model): + _inherit = ['sms.sms'] + + mailing_id = fields.Many2one('mailing.mailing', string='Mass Mailing') + mailing_trace_ids = fields.One2many('mailing.trace', 'sms_sms_id', string='Statistics') + + def _update_body_short_links(self): + """ Override to tweak shortened URLs by adding statistics ids, allowing to + find customer back once clicked. """ + shortened_schema = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + '/r/' + res = dict.fromkeys(self.ids, False) + for sms in self: + if not sms.mailing_id or not sms.body: + res[sms.id] = sms.body + continue + + body = sms.body + for url in re.findall(tools.TEXT_URL_REGEX, body): + if url.startswith(shortened_schema): + body = body.replace(url, url + '/s/%s' % sms.id) + res[sms.id] = body + return res + + def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, delete_all=False): + all_sms_ids = [item['res_id'] for item in iap_results] + if any(sms.mailing_id for sms in self.env['sms.sms'].sudo().browse(all_sms_ids)): + for state in self.IAP_TO_SMS_STATE.keys(): + sms_ids = [item['res_id'] for item in iap_results if item['state'] == state] + traces = self.env['mailing.trace'].sudo().search([ + ('sms_sms_id_int', 'in', sms_ids) + ]) + if traces and state == 'success': + traces.write({'sent': fields.Datetime.now(), 'exception': False}) + elif traces: + traces.set_failed(failure_type=self.IAP_TO_SMS_STATE[state]) + return super(SmsSms, self)._postprocess_iap_sent_sms(iap_results, failure_reason=failure_reason, delete_all=delete_all) diff --git a/addons/mass_mailing_sms/models/utm.py b/addons/mass_mailing_sms/models/utm.py new file mode 100644 index 00000000..67c41648 --- /dev/null +++ b/addons/mass_mailing_sms/models/utm.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + + +class UtmCampaign(models.Model): + _inherit = 'utm.campaign' + + mailing_sms_ids = fields.One2many( + 'mailing.mailing', 'campaign_id', + domain=[('mailing_type', '=', 'sms')], + string='Mass SMS') + mailing_sms_count = fields.Integer('Number of Mass SMS', compute="_compute_mailing_sms_count") + + @api.depends('mailing_sms_ids') + def _compute_mailing_sms_count(self): + for campaign in self: + campaign.mailing_sms_count = len(campaign.mailing_sms_ids) + + def action_create_mass_sms(self): + action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.action_create_mass_mailings_from_campaign") + action['context'] = { + 'default_campaign_id': self.id, + 'default_mailing_type': 'sms', + 'search_default_assigned_to_me': 1, + 'search_default_campaign_id': self.id, + 'default_user_id': self.env.user.id, + } + return action + + def action_redirect_to_mailing_sms(self): + action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing_sms.mailing_mailing_action_sms") + action['context'] = { + 'default_campaign_id': self.id, + 'default_mailing_type': 'sms', + 'search_default_assigned_to_me': 1, + 'search_default_campaign_id': self.id, + 'default_user_id': self.env.user.id, + } + action['domain'] = [('mailing_type', '=', 'sms')] + return action |
