From 3751379f1e9a4c215fb6eb898b4ccc67659b9ace Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Tue, 10 May 2022 21:51:50 +0700 Subject: initial commit 2 --- addons/mass_mailing_sms/wizard/__init__.py | 5 ++ addons/mass_mailing_sms/wizard/mailing_sms_test.py | 39 +++++++++ .../wizard/mailing_sms_test_views.xml | 29 +++++++ addons/mass_mailing_sms/wizard/sms_composer.py | 96 ++++++++++++++++++++++ .../mass_mailing_sms/wizard/sms_composer_views.xml | 16 ++++ 5 files changed, 185 insertions(+) create mode 100644 addons/mass_mailing_sms/wizard/__init__.py create mode 100644 addons/mass_mailing_sms/wizard/mailing_sms_test.py create mode 100644 addons/mass_mailing_sms/wizard/mailing_sms_test_views.xml create mode 100644 addons/mass_mailing_sms/wizard/sms_composer.py create mode 100644 addons/mass_mailing_sms/wizard/sms_composer_views.xml (limited to 'addons/mass_mailing_sms/wizard') diff --git a/addons/mass_mailing_sms/wizard/__init__.py b/addons/mass_mailing_sms/wizard/__init__.py new file mode 100644 index 00000000..eecb3976 --- /dev/null +++ b/addons/mass_mailing_sms/wizard/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import mailing_sms_test +from . import sms_composer diff --git a/addons/mass_mailing_sms/wizard/mailing_sms_test.py b/addons/mass_mailing_sms/wizard/mailing_sms_test.py new file mode 100644 index 00000000..1ea9f871 --- /dev/null +++ b/addons/mass_mailing_sms/wizard/mailing_sms_test.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, exceptions, fields, models, _ +from odoo.addons.phone_validation.tools import phone_validation + + +class MassSMSTest(models.TransientModel): + _name = 'mailing.sms.test' + _description = 'Test SMS Mailing' + + def _default_numbers(self): + return self.env.user.partner_id.phone_sanitized or "" + + numbers = fields.Char(string='Number(s)', required=True, + default=_default_numbers, help='Comma-separated list of phone numbers') + mailing_id = fields.Many2one('mailing.mailing', string='Mailing', required=True, ondelete='cascade') + + def action_send_sms(self): + self.ensure_one() + numbers = [number.strip() for number in self.numbers.split(',')] + sanitize_res = phone_validation.phone_sanitize_numbers_w_record(numbers, self.env.user) + sanitized_numbers = [info['sanitized'] for info in sanitize_res.values() if info['sanitized']] + invalid_numbers = [number for number, info in sanitize_res.items() if info['code']] + if invalid_numbers: + raise exceptions.UserError(_('Following numbers are not correctly encoded: %s, example : "+32 495 85 85 77, +33 545 55 55 55"', repr(invalid_numbers))) + + record = self.env[self.mailing_id.mailing_model_real].search([], limit=1) + body = self.mailing_id.body_plaintext + if record: + # Returns a proper error if there is a syntax error with jinja + body = self.env['mail.render.mixin']._render_template(body, self.mailing_id.mailing_model_real, record.ids)[record.id] + + self.env['sms.api']._send_sms_batch([{ + 'res_id': 0, + 'number': number, + 'content': body, + } for number in sanitized_numbers]) + return True diff --git a/addons/mass_mailing_sms/wizard/mailing_sms_test_views.xml b/addons/mass_mailing_sms/wizard/mailing_sms_test_views.xml new file mode 100644 index 00000000..09656dd1 --- /dev/null +++ b/addons/mass_mailing_sms/wizard/mailing_sms_test_views.xml @@ -0,0 +1,29 @@ + + + + mailing.sms.test.view.form + mailing.sms.test + +
+

+ Send a sample SMS for testing purpose to the numbers below (comma-separated list). +

+ + + + +
+
+
+
+
+ + + Test SMS Marketing + mailing.sms.test + form + new + +
diff --git a/addons/mass_mailing_sms/wizard/sms_composer.py b/addons/mass_mailing_sms/wizard/sms_composer.py new file mode 100644 index 00000000..b8d13b7f --- /dev/null +++ b/addons/mass_mailing_sms/wizard/sms_composer.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import werkzeug.urls + +from odoo import fields, models, _ + + +class SMSComposer(models.TransientModel): + _inherit = 'sms.composer' + + # mass mode with mass sms + mass_sms_allow_unsubscribe = fields.Boolean('Include opt-out link', default=True) + mailing_id = fields.Many2one('mailing.mailing', string='Mailing') + utm_campaign_id = fields.Many2one('utm.campaign', string='Campaign') + + # ------------------------------------------------------------ + # Mass mode specific + # ------------------------------------------------------------ + + def _get_unsubscribe_url(self, res_id, trace_code, number): + base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + return werkzeug.urls.url_join( + base_url, + '/sms/%s/%s' % (self.mailing_id.id, trace_code) + ) + + def _prepare_mass_sms_trace_values(self, record, sms_values): + trace_code = self.env['mailing.trace']._get_random_code() + trace_values = { + 'model': self.res_model, + 'res_id': record.id, + 'trace_type': 'sms', + 'mass_mailing_id': self.mailing_id.id, + 'sms_number': sms_values['number'], + 'sms_code': trace_code, + } + if sms_values['state'] == 'error': + if sms_values['error_code'] == 'sms_number_format': + trace_values['sent'] = fields.Datetime.now() + trace_values['bounced'] = fields.Datetime.now() + else: + trace_values['exception'] = fields.Datetime.now() + elif sms_values['state'] == 'canceled': + trace_values['ignored'] = fields.Datetime.now() + else: + if self.mass_sms_allow_unsubscribe: + sms_values['body'] = '%s\n%s' % (sms_values['body'] or '', _('STOP SMS : %s', self._get_unsubscribe_url(record.id, trace_code, sms_values['number']))) + return trace_values + + def _get_blacklist_record_ids(self, records, recipients_info): + """ Consider opt-outed contact as being blacklisted for that specific + mailing. """ + res = super(SMSComposer, self)._get_blacklist_record_ids(records, recipients_info) + if self.mailing_id: + optout_res_ids = self.mailing_id._get_opt_out_list_sms() + res += optout_res_ids + return res + + def _get_done_record_ids(self, records, recipients_info): + """ A/B testing could lead to records having been already mailed. """ + res = super(SMSComposer, self)._get_done_record_ids(records, recipients_info) + if self.mailing_id: + seen_ids, seen_list = self.mailing_id._get_seen_list_sms() + res += seen_ids + return res + + def _prepare_body_values(self, records): + all_bodies = super(SMSComposer, self)._prepare_body_values(records) + if self.mailing_id: + tracker_values = self.mailing_id._get_link_tracker_values() + for sms_id, body in all_bodies.items(): + body = self.env['mail.render.mixin'].sudo()._shorten_links_text(body, tracker_values) + all_bodies[sms_id] = body + return all_bodies + + def _prepare_mass_sms_values(self, records): + result = super(SMSComposer, self)._prepare_mass_sms_values(records) + if self.composition_mode == 'mass' and self.mailing_id: + for record in records: + sms_values = result[record.id] + + trace_values = self._prepare_mass_sms_trace_values(record, sms_values) + sms_values.update({ + 'mailing_id': self.mailing_id.id, + 'mailing_trace_ids': [(0, 0, trace_values)], + }) + return result + + def _prepare_mass_sms(self, records, sms_record_values): + sms_all = super(SMSComposer, self)._prepare_mass_sms(records, sms_record_values) + if self.mailing_id: + updated_bodies = sms_all._update_body_short_links() + for sms in sms_all: + sms.body = updated_bodies[sms.id] + return sms_all diff --git a/addons/mass_mailing_sms/wizard/sms_composer_views.xml b/addons/mass_mailing_sms/wizard/sms_composer_views.xml new file mode 100644 index 00000000..139338c7 --- /dev/null +++ b/addons/mass_mailing_sms/wizard/sms_composer_views.xml @@ -0,0 +1,16 @@ + + + + sms.composer.views.inherit.sms + sms.composer + + + + + + + + + + -- cgit v1.2.3