diff --git a/addons/sms/__manifest__.py b/addons/sms/__manifest__.py index ccfae7f9049..9be1a884b13 100644 --- a/addons/sms/__manifest__.py +++ b/addons/sms/__manifest__.py @@ -16,6 +16,7 @@ The service is provided by the In App Purchase Odoo platform. 'wizard/sms_cancel_views.xml', 'wizard/sms_composer_views.xml', 'wizard/sms_resend_views.xml', + 'views/ir_actions_views.xml', 'views/res_config_settings_views.xml', 'views/res_partner_views.xml', 'views/assets.xml', diff --git a/addons/sms/models/__init__.py b/addons/sms/models/__init__.py index 4adcd67ab64..aab4ae27445 100644 --- a/addons/sms/models/__init__.py +++ b/addons/sms/models/__init__.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import ir_actions from . import mail_followers from . import mail_message from . import mail_notification diff --git a/addons/sms/models/ir_actions.py b/addons/sms/models/ir_actions.py new file mode 100644 index 00000000000..60abc9e0520 --- /dev/null +++ b/addons/sms/models/ir_actions.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class ServerActions(models.Model): + """ Add SMS option in server actions. """ + _name = 'ir.actions.server' + _inherit = ['ir.actions.server'] + + state = fields.Selection(selection_add=[ + ('sms', 'Send SMS Text Message'), + ]) + # SMS + sms_template_id = fields.Many2one( + 'sms.template', 'SMS Template', ondelete='set null', + domain="[('model_id', '=', model_id)]", + ) + sms_mass_keep_log = fields.Boolean('Log a note', default=True) + + @api.constrains('state', 'model_id') + def _check_sms_capability(self): + for action in self: + if action.state == 'sms' and not action.model_id.is_mail_thread: + raise ValidationError(_("Sending SMS can only be done on a mail.thread model")) + + @api.model + def run_action_sms_multi(self, action, eval_context=None): + # TDE CLEANME: when going to new api with server action, remove action + if not action.sms_template_id or self._is_recompute(action): + return False + + records = eval_context.get('records') or eval_context.get('record') + if not records: + return False + + composer = self.env['sms.composer'].with_context( + default_res_model=records._name, + default_res_ids=records.ids, + default_composition_mode='mass', + default_template_id=action.sms_template_id.id, + default_mass_keep_log=action.sms_mass_keep_log, + ).create({}) + composer.action_send_sms() + return False diff --git a/addons/sms/views/ir_actions_views.xml b/addons/sms/views/ir_actions_views.xml new file mode 100644 index 00000000000..8c6e3b72c5c --- /dev/null +++ b/addons/sms/views/ir_actions_views.xml @@ -0,0 +1,19 @@ + + + + + ir.actions.server.view.form.inherit.sms + ir.actions.server + + + + + + + + + + diff --git a/addons/test_mail_full/tests/__init__.py b/addons/test_mail_full/tests/__init__.py index 8c7cd81f4ae..b64df4304a9 100644 --- a/addons/test_mail_full/tests/__init__.py +++ b/addons/test_mail_full/tests/__init__.py @@ -5,5 +5,6 @@ from . import test_sms_composer from . import test_sms_management from . import test_sms_performance from . import test_sms_post +from . import test_sms_server_actions from . import test_sms_sms from . import test_sms_template diff --git a/addons/test_mail_full/tests/test_sms_server_actions.py b/addons/test_mail_full/tests/test_sms_server_actions.py new file mode 100644 index 00000000000..506513c524a --- /dev/null +++ b/addons/test_mail_full/tests/test_sms_server_actions.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +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 TestSmsTemplate(test_mail_full_common.BaseFunctionalTest, sms_common.MockSMS, test_mail_common.TestRecipients): + + @classmethod + def setUpClass(cls): + super(TestSmsTemplate, cls).setUpClass() + 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_2 = cls.env['mail.test.sms'].with_context(**cls._test_context).create({ + 'name': 'Test Record 2', + 'customer_id': False, + 'phone_nbr': cls.test_numbers[0], + }) + + model_id = cls.env['ir.model']._get('mail.test.sms').id + cls.sms_template = cls.env['sms.template'].create({ + 'name': 'Test Template', + 'model_id': model_id, + 'body': 'Dear ${object.display_name} this is an SMS.' + }) + + cls.action = cls.env['ir.actions.server'].create({ + 'name': 'Test SMS Action', + 'model_id': model_id, + 'state': 'sms', + 'sms_template_id': cls.sms_template.id, + }) + + def test_action_sms(self): + context = { + 'active_model': 'mail.test.sms', + 'active_ids': (self.test_record | self.test_record_2).ids, + } + + with self.sudo('employee'), self.mockSMSGateway(): + self.action.with_user(self.env.user).with_context(**context).run() + + self.assertSMSOutgoing(self.test_record.customer_id, None, 'Dear %s this is an SMS.' % self.test_record.display_name) + self.assertSMSOutgoing(self.env['res.partner'], self.test_numbers_san[0], 'Dear %s this is an SMS.' % self.test_record_2.display_name) + + def test_action_sms_single(self): + context = { + 'active_model': 'mail.test.sms', + 'active_id': self.test_record.id, + } + + with self.sudo('employee'), self.mockSMSGateway(): + self.action.with_user(self.env.user).with_context(**context).run() + self.assertSMSOutgoing(self.test_record.customer_id, None, 'Dear %s this is an SMS.' % self.test_record.display_name) + + def test_action_sms_w_log(self): + self.action.sms_mass_keep_log = True + context = { + 'active_model': 'mail.test.sms', + 'active_ids': (self.test_record | self.test_record_2).ids, + } + + with self.sudo('employee'), self.mockSMSGateway(): + self.action.with_user(self.env.user).with_context(**context).run() + + self.assertSMSNotification([{'partner': self.test_record.customer_id, 'state': 'ready'}], 'Dear %s this is an SMS.' % self.test_record.display_name) + self.assertSMSNotification([{'partner': self.env['res.partner'], 'number': self.test_numbers_san[0], 'state': 'ready'}], 'Dear %s this is an SMS.' % self.test_record_2.display_name) diff --git a/odoo/addons/base/views/ir_cron_views.xml b/odoo/addons/base/views/ir_cron_views.xml index 562f15e02d6..97e801e2fd8 100644 --- a/odoo/addons/base/views/ir_cron_views.xml +++ b/odoo/addons/base/views/ir_cron_views.xml @@ -12,20 +12,18 @@ - - - - + + +