[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:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user