From 7f83f510e73c25db591a751a33470b8bf2c17e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 2 Aug 2023 12:43:55 +0000 Subject: [PATCH] [REF] various, calendar_sms: remove '_sms_get_default_partners' RATIONALE Simplify field management for mail / phone / sms flows. Make it working out of the box, easier to use and tweak. SPECIFICATIONS '_sms_get_default_partners' exists in SMS to find default customers to notify when sending automated SMS. It can be replaced by '_mail_get_partners' helper available on BaseModel in mail. A specific case exists in calendar where it was overridden to avoid notifying attendees that declined the event, notably for alarms. This feature has been moved directly in the reminder sending method, to keep behavior coherent. Test is updated accordingly, and is now really using the SMS mocks to simulate the sending. Task-3422449 (Mail, Phone: Move and improve field helpers) Part-of: odoo/odoo#130468 --- addons/calendar_sms/models/calendar_event.py | 11 +++----- .../calendar_sms/tests/test_calendar_sms.py | 26 ++++++++++++------- addons/sms/models/mail_followers.py | 4 +-- addons/sms/models/mail_thread.py | 17 +++--------- addons/sms/models/res_partner.py | 6 ----- addons/sms/wizard/sms_composer.py | 2 +- 6 files changed, 28 insertions(+), 38 deletions(-) diff --git a/addons/calendar_sms/models/calendar_event.py b/addons/calendar_sms/models/calendar_event.py index 1a226cddbde..a3687bee0cc 100644 --- a/addons/calendar_sms/models/calendar_event.py +++ b/addons/calendar_sms/models/calendar_event.py @@ -7,17 +7,14 @@ from odoo.exceptions import UserError class CalendarEvent(models.Model): _inherit = 'calendar.event' - def _sms_get_default_partners(self): - """ Method overridden from mail.thread (defined in the sms module). - SMS text messages will be sent to attendees that haven't declined the event(s). - """ - return self.mapped('attendee_ids').filtered(lambda att: att.state != 'declined' and att.partner_id.phone_sanitized).mapped('partner_id') - def _do_sms_reminder(self, alarms): """ Send an SMS text reminder to attendees that haven't declined the event """ for event in self: + declined_partners = event.attendee_ids.filtered_domain([('state', '=', 'declined')]).partner_id for alarm in alarms: - partners = event._sms_get_default_partners() + partners = event._mail_get_partners()[event.id].filtered( + lambda partner: partner.phone_sanitized and partner not in declined_partners + ) if event.user_id and not alarm.sms_notify_responsible: partners -= event.user_id.partner_id event._message_sms_with_template( diff --git a/addons/calendar_sms/tests/test_calendar_sms.py b/addons/calendar_sms/tests/test_calendar_sms.py index 33444d8d21f..93eeb446d77 100644 --- a/addons/calendar_sms/tests/test_calendar_sms.py +++ b/addons/calendar_sms/tests/test_calendar_sms.py @@ -3,10 +3,12 @@ from datetime import datetime -from odoo.tests.common import SingleTransactionCase +from odoo.addons.sms.tests.common import SMSCommon +from odoo.tests import tagged -class TestCalendarSms(SingleTransactionCase): +@tagged('sms') +class TestCalendarSms(SMSCommon): @classmethod def setUpClass(cls): @@ -21,13 +23,19 @@ class TestCalendarSms(SingleTransactionCase): 'name': 'Partner With No Phone Number', 'country_id': cls.env.ref('base.be').id, }) + cls.event = cls.env['calendar.event'].create({ + 'alarm_ids': [(0, 0, { + 'alarm_type': 'sms', + 'name': 'SMS Reminder', + })], + 'name': "Boostrap vs Foundation", + 'partner_ids': [(6, 0, [cls.partner_phone.id, cls.partner_no_phone.id])], + 'start': datetime(2022, 1, 1, 11, 11), + 'stop': datetime(2022, 2, 2, 22, 22), + }) def test_attendees_with_number(self): """Test if only partners with sanitized number are returned.""" - attendees = self.env['calendar.event'].create({ - 'name': "Boostrap vs Foundation", - 'start': datetime(2022, 1, 1, 11, 11), - 'stop': datetime(2022, 2, 2, 22, 22), - 'partner_ids': [(6, 0, [self.partner_phone.id, self.partner_no_phone.id])], - })._sms_get_default_partners() - self.assertEqual(len(attendees), 1, "There should be only one partner retrieved") + with self.mockSMSGateway(): + self.event._do_sms_reminder(self.event.alarm_ids) + self.assertEqual(len(self._sms), 1, "There should be only one partner retrieved") diff --git a/addons/sms/models/mail_followers.py b/addons/sms/models/mail_followers.py index eb72da59d95..073f419a9a9 100644 --- a/addons/sms/models/mail_followers.py +++ b/addons/sms/models/mail_followers.py @@ -14,8 +14,8 @@ class Followers(models.Model): if pids is None and records: records_pids = dict( - (record.id, record._sms_get_default_partners().ids) - for record in records + (rec_id, partners.ids) + for rec_id, partners in records._mail_get_partners().items() ) elif pids and records: records_pids = dict((record.id, pids) for record in records) diff --git a/addons/sms/models/mail_thread.py b/addons/sms/models/mail_thread.py index 971cbf64304..22c010d4936 100644 --- a/addons/sms/models/mail_thread.py +++ b/addons/sms/models/mail_thread.py @@ -42,15 +42,6 @@ class MailThread(models.AbstractModel): def _search_message_has_sms_error(self, operator, operand): return ['&', ('message_ids.has_sms_error', operator, operand), ('message_ids.author_id', '=', self.env.user.partner_id.id)] - def _sms_get_default_partners(self): - """ This method will likely need to be overridden by inherited models. - :returns partners: recordset of res.partner - """ - partners = self.env['res.partner'] - for fname in self._mail_get_partner_fields(): - partners = partners.union(*self.mapped(fname)) # ensure ordering - return partners - def _sms_get_recipients_info(self, force_field=False, partner_fallback=True): """" Get SMS recipient information on current record set. This method checks for numbers and sanitation in order to centralize computation. @@ -65,11 +56,11 @@ class MailThread(models.AbstractModel): :param force_field: either give a specific field to find phone number, either generic heuristic is used to find one based on ``_phone_get_number_fields``; :param partner_fallback: if no value found in the record, check its customer - values based on ``_sms_get_default_partners``; + values based on ``_mail_get_partners``; :return dict: record.id: { 'partner': a res.partner recordset that is the customer (void or singleton) - linked to the recipient. See ``_sms_get_default_partners``; + linked to the recipient. See ``_mail_get_partners``; 'sanitized': sanitized number to use (coming from record's field or partner's phone fields). Set to False is number impossible to parse and format; 'number': original number before sanitation; @@ -84,9 +75,9 @@ class MailThread(models.AbstractModel): tocheck_fields = [force_field] if force_field else self._phone_get_number_fields() for record in self: all_numbers = [record[fname] for fname in tocheck_fields if fname in record] - all_partners = record._sms_get_default_partners() + all_partners = record._mail_get_partners()[record.id] - valid_number = False + valid_number, fname = False, False for fname in [f for f in tocheck_fields if f in record]: valid_number = record._phone_format(fname=fname) if valid_number: diff --git a/addons/sms/models/res_partner.py b/addons/sms/models/res_partner.py index 74769276e5f..4f7c9289743 100644 --- a/addons/sms/models/res_partner.py +++ b/addons/sms/models/res_partner.py @@ -7,9 +7,3 @@ from odoo import models class ResPartner(models.Model): _name = 'res.partner' _inherit = ['mail.thread.phone', 'res.partner'] - - def _sms_get_default_partners(self): - """ Override of mail.thread method. - SMS recipients on partners are the partners themselves. - """ - return self diff --git a/addons/sms/wizard/sms_composer.py b/addons/sms/wizard/sms_composer.py index 8ace46e786f..6cb0b8db911 100644 --- a/addons/sms/wizard/sms_composer.py +++ b/addons/sms/wizard/sms_composer.py @@ -123,7 +123,7 @@ class SendSMS(models.TransientModel): continue records.ensure_one() res = records._sms_get_recipients_info(force_field=composer.number_field_name, partner_fallback=False) - composer.recipient_single_description = res[records.id]['partner'].name or records._sms_get_default_partners().display_name + composer.recipient_single_description = res[records.id]['partner'].name or records._mail_get_partners()[records[0].id].display_name composer.recipient_single_number = res[records.id]['number'] or '' if not composer.recipient_single_number_itf: composer.recipient_single_number_itf = res[records.id]['number'] or ''