Files
odoo_source/addons/test_mail_full/tests/test_sms_post.py
T
Thibault DelavalléeandPierre Rousseau bdebcab0ce [REF] sms: refactor message_post using SMS notifications
Purpose of this commit is to better include SMS notifications when posting a
message. SMS is now just another way of notifying people along with Inbox and
email. Following recent mail merge improving notification mechanism [1] we
have to define a _notify_record_by_sms method on mail.thread.

When a message_post is done using message_type being ``sms`` notification type
of customers is set to sms. Customers can be computed on model (generally based
on partner_id field) or directly set usign partner°ids. Notification model is
updated to store this information directly inside the notification itself.

An new ``_message_sms`` helper method is introduced in SMS module allowing
to send messages using sms type and notification with a reduced parameters
number. It is just a shortcut to message_post, easier to use. Either it
computes default recipients on the record set, either it is based on given
partners and numbers to notify.

The following use cases are notably supported

  * default computation: find customer, notify by sms;
  * force recipients to notify by sms (partner_ids);
  * give a set of numbers to notify by sms (sms_nubmers), not necessarily
    linked to existing partners;
  * force number / customer relationship independently of mobile number defined
    on customer (for example when sending an SMS directly from a mobile field
    on a lead linked to a customer);

Tests are updated accordingly. Performance tests are added in order to have
some insights on queries generated when sending SMS, like already done for
mail.thread alone.

Related to task 1922163
Linked to PR #33510

[1] see be27955136: performance and notification code improvements

Co-Authored-By: Thibault Delavallee <tde@odoo.com>
Co-Authored-By: Pierre Rousseau <pro@odoo.com>
2019-07-12 14:54:11 +00:00

292 lines
16 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.sms.tests import common as sms_common
from odoo.addons.test_mail.tests import common as test_mail_common
from odoo.addons.test_mail_full.tests import common as test_mail_full_common
class TestSMSPost(test_mail_full_common.BaseFunctionalTest, sms_common.MockSMS, test_mail_common.MockEmails, test_mail_common.TestRecipients):
@classmethod
def setUpClass(cls):
super(TestSMSPost, cls).setUpClass()
cls._test_body = 'VOID CONTENT'
cls.partner_numbers = [
phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164')
for partner in (cls.partner_1 | cls.partner_2)
]
cls.test_record = cls.env['mail.test.sms'].with_context(**cls._test_context).create({
'name': 'Test',
'customer_id': cls.partner_1.id,
'mobile_nbr': cls.test_numbers[0],
'phone_nbr': cls.test_numbers[1],
})
cls.test_record = cls._reset_mail_context(cls.test_record)
def test_message_sms_internals_body(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms('<p>Mega SMS<br/>Top moumoutte</p>', partner_ids=self.partner_1.ids)
self.assertEqual(messages.body, '<p>Mega SMS<br>Top moumoutte</p>')
self.assertSMSNotification([{'partner': self.partner_1}], 'Mega SMS\nTop moumoutte', messages)
def test_message_sms_internals_check_existing(self):
with self.sudo('employee'), self.mockSMSGateway(sim_error='wrong_format_number'):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=self.partner_1.ids)
self.assertSMSNotification([{'partner': self.partner_1, 'state': 'exception', 'failure_type': 'sms_number_format'}], self._test_body, messages)
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
test_record._notify_record_by_sms(messages, {'partners': [{'id': self.partner_1.id, 'notif': 'sms'}]}, check_existing=True)
self.assertSMSNotification([{'partner': self.partner_1}], self._test_body, messages)
def test_message_sms_internals_sms_numbers(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=self.partner_1.ids, sms_numbers=self.random_numbers)
self.assertSMSNotification([{'partner': self.partner_1}, {'number': self.random_numbers_san[0]}, {'number': self.random_numbers_san[1]}], self._test_body, messages)
def test_message_sms_internals_pid_to_number(self):
pid_to_number = {
self.partner_1.id: self.random_numbers[0],
self.partner_2.id: self.random_numbers[1],
}
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2).ids, sms_pid_to_number=pid_to_number)
self.assertSMSNotification([
{'partner': self.partner_1, 'number': self.random_numbers_san[0]},
{'partner': self.partner_2, 'number': self.random_numbers_san[1]}],
self._test_body, messages)
def test_message_sms_model_partner(self):
with self.sudo('employee'), self.mockSMSGateway():
messages = self.partner_1._message_sms(self._test_body)
messages |= self.partner_2._message_sms(self._test_body)
self.assertSMSNotification([{'partner': self.partner_1}, {'partner': self.partner_2}], self._test_body, messages)
def test_message_sms_model_partner_fallback(self):
self.partner_1.write({'mobile': False, 'phone': self.random_numbers[0]})
with self.mockSMSGateway():
messages = self.partner_1._message_sms(self._test_body)
messages |= self.partner_2._message_sms(self._test_body)
self.assertSMSNotification([{'partner': self.partner_1, 'number': self.random_numbers_san[0]}, {'partner': self.partner_2}], self._test_body, messages)
def test_message_sms_model_w_partner_only(self):
with self.sudo('employee'):
record = self.env['mail.test.sms.partner'].create({'partner_id': self.partner_1.id})
with self.mockSMSGateway():
messages = record._message_sms(self._test_body)
self.assertSMSNotification([{'partner': self.partner_1}], self._test_body, messages)
def test_message_sms_model_w_partner_only_void(self):
with self.sudo('employee'):
record = self.env['mail.test.sms.partner'].create({'partner_id': False})
with self.mockSMSGateway():
messages = record._message_sms(self._test_body)
# should not crash but no sms / no recipients
notifs = self.env['mail.notification'].search([('mail_message_id', 'in', messages.ids)])
self.assertFalse(notifs)
def test_message_sms_on_field_w_partner(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, number_field='mobile_nbr')
self.assertSMSNotification([{'partner': self.partner_1, 'number': self.test_record.mobile_nbr}], self._test_body, messages)
def test_message_sms_on_field_wo_partner(self):
self.test_record.write({'customer_id': False})
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, number_field='mobile_nbr')
self.assertSMSNotification([{'number': self.test_record.mobile_nbr}], self._test_body, messages)
def test_message_sms_on_field_wo_partner_default_field(self):
self.test_record.write({'customer_id': False})
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body)
self.assertSMSNotification([{'number': self.test_numbers_san[1]}], self._test_body, messages)
def test_message_sms_on_field_wo_partner_default_field_2(self):
self.test_record.write({'customer_id': False, 'phone_nbr': False})
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body)
self.assertSMSNotification([{'number': self.test_numbers_san[0]}], self._test_body, messages)
def test_message_sms_on_numbers(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, sms_numbers=self.random_numbers_san)
self.assertSMSNotification([{'number': self.random_numbers_san[0]}, {'number': self.random_numbers_san[1]}], self._test_body, messages)
def test_message_sms_on_numbers_sanitization(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, sms_numbers=self.random_numbers)
self.assertSMSNotification([{'number': self.random_numbers_san[0]}, {'number': self.random_numbers_san[1]}], self._test_body, messages)
def test_message_sms_on_partner_ids(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2).ids)
self.assertSMSNotification([{'partner': self.partner_1}, {'partner': self.partner_2}], self._test_body, messages)
def test_message_sms_on_partner_ids_default(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body)
self.assertSMSNotification([{'partner': self.test_record.customer_id, 'number': self.test_numbers_san[1]}], self._test_body, messages)
def test_message_sms_on_partner_ids_w_numbers(self):
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=self.partner_1.ids, sms_numbers=self.random_numbers[:1])
self.assertSMSNotification([{'partner': self.partner_1}, {'number': self.random_numbers_san[0]}], self._test_body, messages)
class TestSMSPostException(test_mail_full_common.BaseFunctionalTest, sms_common.MockSMS, test_mail_common.MockEmails, test_mail_common.TestRecipients):
@classmethod
def setUpClass(cls):
super(TestSMSPostException, cls).setUpClass()
cls._test_body = 'VOID CONTENT'
cls.test_record = cls.env['mail.test.sms'].with_context(**cls._test_context).create({
'name': 'Test',
'customer_id': cls.partner_1.id,
})
cls.test_record = cls._reset_mail_context(cls.test_record)
cls.partner_3 = cls.env['res.partner'].with_context({
'mail_create_nolog': True,
'mail_create_nosubscribe': True,
'mail_notrack': True,
'no_reset_password': True,
}).create({
'name': 'Ernestine Loubine',
'email': 'ernestine.loubine@agrolait.com',
'country_id': cls.env.ref('base.be').id,
'mobile': '0475556644',
})
def test_message_sms_w_numbers_invalid(self):
random_numbers = self.random_numbers + ['6988754']
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, sms_numbers=random_numbers)
# invalid numbers are still given to IAP currently as they are
self.assertSMSNotification([{'number': self.random_numbers_san[0]}, {'number': self.random_numbers_san[1]}, {'number': random_numbers[2]}], self._test_body, messages)
def test_message_sms_w_partners_nocountry(self):
self.test_record.customer_id.write({
'mobile': self.random_numbers[0],
'phone': self.random_numbers[1],
'country_id': False,
})
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=self.test_record.customer_id.ids)
self.assertSMSNotification([{'partner': self.test_record.customer_id}], self._test_body, messages)
def test_message_sms_w_partners_falsy(self):
# TDE FIXME: currently sent to IAP
self.test_record.customer_id.write({
'mobile': 'youpie',
'phone': 'youpla',
})
with self.sudo('employee'), self.mockSMSGateway():
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=self.test_record.customer_id.ids)
# self.assertSMSNotification({self.test_record.customer_id: {}}, {}, self._test_body, messages)
def test_message_sms_w_numbers_sanitization_duplicate(self):
pass
# TDE FIXME: not sure
# random_numbers = self.random_numbers + [self.random_numbers[1]]
# random_numbers_san = self.random_numbers_san + [self.random_numbers_san[1]]
# with self.sudo('employee'), self.mockSMSGateway():
# messages = self.test_record._message_sms(self._test_body, sms_numbers=random_numbers)
# self.assertSMSNotification({}, {random_numbers_san[0]: {}, random_numbers_san[1]: {}, random_numbers_san[2]: {}}, self._test_body, messages)
def test_message_sms_crash_credit(self):
with self.sudo('employee'), self.mockSMSGateway(sim_error='credit'):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2).ids)
self.assertSMSNotification([
{'partner': self.partner_1, 'state': 'exception', 'failure_type': 'sms_credit'},
{'partner': self.partner_2, 'state': 'exception', 'failure_type': 'sms_credit'},
], self._test_body, messages)
def test_message_sms_crash_credit_single(self):
with self.sudo('employee'), self.mockSMSGateway(nbr_t_error={phone_validation.phone_get_sanitized_record_number(self.partner_2): 'credit'}):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2 | self.partner_3).ids)
self.assertSMSNotification([
{'partner': self.partner_1, 'state': 'sent'},
{'partner': self.partner_2, 'state': 'exception', 'failure_type': 'sms_credit'},
{'partner': self.partner_3, 'state': 'sent'},
], self._test_body, messages)
def test_message_sms_crash_server_crash(self):
with self.sudo('employee'), self.mockSMSGateway(sim_error='jsonrpc_exception'):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2 | self.partner_3).ids)
self.assertSMSNotification([
{'partner': self.partner_1, 'state': 'exception', 'failure_type': 'sms_server'},
{'partner': self.partner_2, 'state': 'exception', 'failure_type': 'sms_server'},
{'partner': self.partner_3, 'state': 'exception', 'failure_type': 'sms_server'},
], self._test_body, messages)
def test_message_sms_crash_wrong_number(self):
with self.sudo('employee'), self.mockSMSGateway(sim_error='wrong_format_number'):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2).ids)
self.assertSMSNotification([
{'partner': self.partner_1, 'state': 'exception', 'failure_type': 'sms_number_format'},
{'partner': self.partner_2, 'state': 'exception', 'failure_type': 'sms_number_format'},
], self._test_body, messages)
def test_message_sms_crash_wrong_number_single(self):
with self.sudo('employee'), self.mockSMSGateway(nbr_t_error={phone_validation.phone_get_sanitized_record_number(self.partner_2): 'wrong_format_number'}):
test_record = self.env['mail.test.sms'].browse(self.test_record.id)
messages = test_record._message_sms(self._test_body, partner_ids=(self.partner_1 | self.partner_2 | self.partner_3).ids)
self.assertSMSNotification([
{'partner': self.partner_1, 'state': 'sent'},
{'partner': self.partner_2, 'state': 'exception', 'failure_type': 'sms_number_format'},
{'partner': self.partner_3, 'state': 'sent'},
], self._test_body, messages)