[IMP] sms: improve composer behavior

PURPOSE

Purpose of this commit is to add options and improve sms composer behavior.
Followup of merge 4287481bf0 .

SPECIFICATIONS

  * mass mode: add an option to keep archives when doing mass sms. This mode
    is actually a _message_sms in batch using the note subtype to speedup the
    process;
  * improve _message_sms_schedule_mass to allow more fine-tuning of options
    when calling it;
  * do not block sending SMS in batch if some recipients are invalid. Indeed
    using notifications there will be traces of failed SMS;
  * avoid reload of form view;

Linked to task 1925950 and 1935280
Part of PR #34864
This commit is contained in:
Thibault Delavallée
2019-07-18 09:19:04 +00:00
parent 1bfdf9219d
commit ac212ae65d
7 changed files with 55 additions and 22 deletions
+9 -2
View File
@@ -106,7 +106,7 @@ class MailThread(models.AbstractModel):
result[record.id] = {'partner': self.env['res.partner'], 'sanitized': False, 'number': False}
return result
def _message_sms_schedule_mass(self, body='', template=False, active_domain=None):
def _message_sms_schedule_mass(self, body='', template=False, active_domain=None, **composer_values):
""" Shortcut method to schedule a mass sms sending on a recordset.
:param template: an optional sms.template record;
@@ -125,7 +125,14 @@ class MailThread(models.AbstractModel):
else:
composer_context['default_res_ids'] = self.ids
composer = self.env['sms.composer'].with_context(**composer_context).create({})
create_vals = {
'mass_force_send': False,
'mass_keep_log': False,
}
if composer_values:
create_vals.update(composer_values)
composer = self.env['sms.composer'].with_context(**composer_context).create(create_vals)
return composer._action_send_sms()
def _message_sms_with_template(self, template=False, template_xmlid=False, template_fallback='', partner_ids=False, **kwargs):
+2 -1
View File
@@ -41,7 +41,8 @@ class SmsSms(models.Model):
"""
for batch_ids in self._split_batch():
self.browse(batch_ids)._send(delete_all=delete_all, raise_exception=raise_exception)
if auto_commit is True:
# auto-commit if asked except in testing mode
if auto_commit is True and not getattr(threading.currentThread(), 'testing', False):
self._cr.commit()
@api.model
+5 -2
View File
@@ -155,6 +155,9 @@ class MockSMS(common.BaseCase):
self.assertSMSFailed(partner, number, recipient_info['failure_type'], content)
elif state == 'canceled':
self.assertSMSCanceled(partner, number, recipient_info.get('failure_type', False), content)
else:
raise NotImplementedError('Not implemented')
for message in messages:
self.assertEqual(content, tools.html2plaintext(message.body).rstrip('\n'))
if messages is not None:
for message in messages:
self.assertEqual(content, tools.html2plaintext(message.body).rstrip('\n'))
+16 -16
View File
@@ -54,6 +54,7 @@ class SendSMS(models.TransientModel):
active_domain = fields.Text('Active domain', readonly=True)
# options for comment and mass mode
mass_keep_log = fields.Boolean('Keep a note on document')
mass_force_send = fields.Boolean('Send directly')
# recipients
recipient_description = fields.Text('Recipients (Partners)', compute='_compute_description')
recipient_invalid = fields.Text('Invalid recipients', compute='_compute_description')
@@ -134,14 +135,9 @@ class SendSMS(models.TransientModel):
# ------------------------------------------------------------
def action_send_sms(self):
if self.recipient_invalid:
if self.composition_mode in ('numbers', 'comment') and self.recipient_invalid:
raise UserError(_('Invalid recipients: %s') % self.recipient_invalid)
self._action_send_sms()
if self.composition_mode == 'comment':
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
return False
def _action_send_sms(self, force_send=False):
@@ -152,7 +148,7 @@ class SendSMS(models.TransientModel):
if records is not None and issubclass(type(records), self.pool['mail.thread']):
return self._action_send_sms_comment(records)
return self._action_send_sms_numbers()
elif self.mass_keep_log:
elif self.mass_keep_log and records is not None and issubclass(type(records), self.pool['mail.thread']):
return self._action_send_sms_mass_w_log(records)
else:
return self._action_send_sms_mass(records)
@@ -184,17 +180,21 @@ class SendSMS(models.TransientModel):
record_values = self._prepare_mass_sms_values(records)
sms_create_vals = [record_values[record.id] for record in records]
sms = self.env['sms.sms'].sudo().create(sms_create_vals)
if sms and self.mass_force_send:
sms.send(auto_commit=False, raise_exception=False)
return sms
def _action_send_sms_mass_w_log(self):
records = self._get_records()
if records and hasattr(records, '_message_sms'):
subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note')
for record in records:
record._message_sms(self.body, subtype_id=subtype_id, partner_ids=False, sms_numbers=None)
else:
self.env['sms.api']._send_sms(self.numbers, self.body)
return True
def _action_send_sms_mass_w_log(self, records=None):
records = records if records is not None else self._get_records()
all_bodies = self._prepare_body_values(records=records)
subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note')
messages = self.env['mail.message']
for record in records:
messages |= record._message_sms(all_bodies[record.id], subtype_id=subtype_id, partner_ids=False, sms_numbers=None, put_in_queue=not self.mass_force_send)
return messages
# ------------------------------------------------------------
# Mass mode specific
+2
View File
@@ -12,6 +12,7 @@
<field name="res_ids" invisible="1"/>
<field name="active_domain" invisible="1"/>
<field name="res_model" invisible="1"/>
<field name="mass_force_send" invisible="1"/>
<field name="number_field_name" invisible="1"/>
<field name="partner_ids" invisible="1"/>
<field name="numbers" invisible="1"/>
@@ -61,6 +62,7 @@
<group>
<group>
<field name="template_id" options="{'no_create': True}" attrs="{'invisible': [('composition_mode', '!=', 'mass')]}"/>
<field name="mass_keep_log" attrs="{'invisible': [('composition_mode', '!=', 'mass')]}"/>
</group>
</group>
</sheet>
+5 -1
View File
@@ -18,5 +18,9 @@ class BaseFunctionalTest(test_mail_common.BaseFunctionalTest):
cls.random_numbers_str = '+32456998877, 0456665544'
cls.random_numbers = cls.random_numbers_str.split(', ')
cls.random_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.random_numbers]
cls.test_numbers = ['+32456010203', '0456 04 05 06']
cls.test_numbers = ['+32456010203', '0456 04 05 06', '0032456070809']
cls.test_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.test_numbers]
# some numbers for mass testing
cls.mass_numbers = ['04561%s2%s3%s' % (x, x, x) for x in range(0, 10)]
cls.mass_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.mass_numbers]
@@ -300,6 +300,14 @@ class TestSMSComposerMass(test_mail_full_common.BaseFunctionalTest, sms_common.M
for record in self.records:
self.assertSMSOutgoing(record.customer_id, None, self._test_body)
def test_message_schedule_sms_w_log(self):
with self.sudo('employee'):
with self.mockSMSGateway():
self.env['mail.test.sms'].browse(self.records.ids)._message_sms_schedule_mass(body=self._test_body, mass_keep_log=True)
for record in self.records:
self.assertSMSNotification([{'partner': record.customer_id, 'state': 'ready'}], self._test_body)
def test_message_schedule_sms_w_template(self):
with self.sudo('employee'):
with self.mockSMSGateway():
@@ -307,3 +315,11 @@ class TestSMSComposerMass(test_mail_full_common.BaseFunctionalTest, sms_common.M
for record in self.records:
self.assertSMSOutgoing(record.customer_id, None, 'Dear %s this is an SMS.' % record.display_name)
def test_message_schedule_sms_w_template_and_log(self):
with self.sudo('employee'):
with self.mockSMSGateway():
self.env['mail.test.sms'].browse(self.records.ids)._message_sms_schedule_mass(template=self.sms_template, mass_keep_log=True)
for record in self.records:
self.assertSMSNotification([{'partner': record.customer_id, 'state': 'ready'}], 'Dear %s this is an SMS.' % record.display_name)