From 1b4e0099d4d9c566d2a886a1db1ec6d0432d206c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 25 Aug 2021 08:45:29 +0000 Subject: [PATCH] [MOV][FIX] mail: quickly reorder code parts, remove dead imports, fix code bits Reorganize code to ease future additions understanding and setting code at the right place. Rename some compute methods to have understandable names. Remove dead imports. Fix pytz.utc usage. No functional change comes with this commit. This is only code move. Task-2631873 PR odoo/odoo#75571 --- addons/mail/controllers/discuss.py | 2 +- addons/mail/models/ir_attachment.py | 2 +- addons/mail/models/mail_activity.py | 2 +- addons/mail/models/mail_activity_mixin.py | 2 +- addons/mail/models/mail_activity_type.py | 1 - addons/mail/models/mail_mail.py | 16 ++--- addons/mail/models/mail_message.py | 8 +-- addons/mail/models/mail_notification.py | 26 +++++--- addons/mail/models/res_config_settings.py | 2 - addons/mail/models/res_partner.py | 75 +++++++++++++---------- addons/mail/models/res_users.py | 8 +++ 11 files changed, 87 insertions(+), 57 deletions(-) diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index b9a7454d963..4cfcaacce57 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -118,6 +118,6 @@ class DiscussController(http.Controller): try: records.check_access_rule('read') records.check_access_rights('read') - except: + except Exception: return {} return records._message_get_suggested_recipients() diff --git a/addons/mail/models/ir_attachment.py b/addons/mail/models/ir_attachment.py index 7fe59ec8ee4..6cf408a8a26 100644 --- a/addons/mail/models/ir_attachment.py +++ b/addons/mail/models/ir_attachment.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, models +from odoo import models from odoo.exceptions import AccessError from odoo.http import request diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index d4eae30fe39..a976bb318cc 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -125,7 +125,7 @@ class MailActivity(models.Model): today_default = date.today() today = today_default if tz: - today_utc = pytz.UTC.localize(datetime.utcnow()) + today_utc = pytz.utc.localize(datetime.utcnow()) today_tz = today_utc.astimezone(pytz.timezone(tz)) today = date(year=today_tz.year, month=today_tz.month, day=today_tz.day) diff = (date_deadline - today) diff --git a/addons/mail/models/mail_activity_mixin.py b/addons/mail/models/mail_activity_mixin.py index 3412147c834..b7334dc7c11 100644 --- a/addons/mail/models/mail_activity_mixin.py +++ b/addons/mail/models/mail_activity_mixin.py @@ -187,7 +187,7 @@ class MailActivityMixin(models.AbstractModel): self._cr.execute( query, { - 'today_utc': pytz.UTC.localize(datetime.utcnow()), + 'today_utc': pytz.utc.localize(datetime.utcnow()), 'res_model_table': self._name, 'search_states_int': list(search_states_int) }, diff --git a/addons/mail/models/mail_activity_type.py b/addons/mail/models/mail_activity_type.py index da89c9b8e27..c305919c804 100644 --- a/addons/mail/models/mail_activity_type.py +++ b/addons/mail/models/mail_activity_type.py @@ -21,7 +21,6 @@ class MailActivityType(models.Model): ['&', ('is_mail_thread', '=', True), ('transient', '=', False)]) ] - name = fields.Char('Name', required=True, translate=True) summary = fields.Char('Default Summary', translate=True) sequence = fields.Integer('Sequence', default=10) diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index 64a56c4403d..b36ad00001a 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -28,6 +28,14 @@ class MailMail(models.Model): _order = 'id desc' _rec_name = 'subject' + @api.model + def default_get(self, fields): + # protection for `default_type` values leaking from menu action context (e.g. for invoices) + # To remove when automatic context propagation is removed in web client + if self._context.get('default_type') not in type(self).message_type.base_field.selection: + self = self.with_context(dict(self._context, default_type=None)) + return super(MailMail, self).default_get(fields) + # content mail_message_id = fields.Many2one('mail.message', 'Message', required=True, ondelete='cascade', index=True, auto_join=True) body_html = fields.Text('Rich-text Contents', help="Rich-text/HTML message") @@ -104,14 +112,6 @@ class MailMail(models.Model): self.env['mail.message'].browse(mail_msg_cascade_ids).unlink() return res - @api.model - def default_get(self, fields): - # protection for `default_type` values leaking from menu action context (e.g. for invoices) - # To remove when automatic context propagation is removed in web client - if self._context.get('default_type') not in type(self).message_type.base_field.selection: - self = self.with_context(dict(self._context, default_type=None)) - return super(MailMail, self).default_get(fields) - def action_retry(self): self.filtered(lambda mail: mail.state == 'exception').mark_outgoing() diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index 0f6cc22c419..da8fd308120 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -133,7 +133,7 @@ class Message(models.Model): 'res.partner', 'mail_notification', string='Partners with Need Action', context={'active_test': False}, depends=['notification_ids']) needaction = fields.Boolean( - 'Need Action', compute='_get_needaction', search='_search_needaction', + 'Need Action', compute='_compute_needaction', search='_search_needaction', help='Need Action') has_error = fields.Boolean( 'Has error', compute='_compute_has_error', search='_search_has_error', @@ -146,7 +146,7 @@ class Message(models.Model): starred_partner_ids = fields.Many2many( 'res.partner', 'mail_message_res_partner_starred_rel', string='Favorited By') starred = fields.Boolean( - 'Starred', compute='_get_starred', search='_search_starred', compute_sudo=False, + 'Starred', compute='_compute_starred', search='_search_starred', compute_sudo=False, help='Current user has a starred notification linked to this message') # tracking tracking_value_ids = fields.One2many( @@ -183,7 +183,7 @@ class Message(models.Model): plaintext_ct = '' if not message.body else tools.html2plaintext(message.body) message.description = plaintext_ct[:30] + '%s' % (' [...]' if len(plaintext_ct) >= 30 else '') - def _get_needaction(self): + def _compute_needaction(self): """ Need action on a mail.message = notified on my channel """ my_messages = self.env['mail.notification'].sudo().search([ ('mail_message_id', 'in', self.ids), @@ -212,7 +212,7 @@ class Message(models.Model): @api.depends('starred_partner_ids') @api.depends_context('uid') - def _get_starred(self): + def _compute_starred(self): """ Compute if the message is starred by the current user. """ # TDE FIXME: use SQL starred = self.sudo().filtered(lambda msg: self.env.user.partner_id in msg.starred_partner_ids) diff --git a/addons/mail/models/mail_notification.py b/addons/mail/models/mail_notification.py index 6626432b3cf..1ee834b21a9 100644 --- a/addons/mail/models/mail_notification.py +++ b/addons/mail/models/mail_notification.py @@ -50,6 +50,10 @@ class MailNotification(models.Model): 'Customer is required for inbox / email notification'), ] + # ------------------------------------------------------------ + # CRUD + # ------------------------------------------------------------ + def init(self): self._cr.execute(""" CREATE INDEX IF NOT EXISTS mail_notification_res_partner_id_is_read_notification_status_mail_message_id @@ -73,13 +77,6 @@ class MailNotification(models.Model): vals['read_date'] = fields.Datetime.now() return super(MailNotification, self).write(vals) - def format_failure_reason(self): - self.ensure_one() - if self.failure_type != 'unknown': - return dict(type(self).failure_type.selection).get(self.failure_type, _('No Error')) - else: - return _("Unknown error") + ": %s" % (self.failure_reason or '') - @api.model def _gc_notifications(self, max_age_days=180): domain = [ @@ -90,6 +87,21 @@ class MailNotification(models.Model): ] return self.search(domain).unlink() + # ------------------------------------------------------------ + # TOOLS + # ------------------------------------------------------------ + + def format_failure_reason(self): + self.ensure_one() + if self.failure_type != 'unknown': + return dict(type(self).failure_type.selection).get(self.failure_type, _('No Error')) + else: + return _("Unknown error") + ": %s" % (self.failure_reason or '') + + # ------------------------------------------------------------ + # DISCUSS + # ------------------------------------------------------------ + def _filtered_for_web_client(self): """Returns only the notifications to show on the web client.""" return self.filtered(lambda n: diff --git a/addons/mail/models/res_config_settings.py b/addons/mail/models/res_config_settings.py index 6cae4f3b0d5..f2272520160 100644 --- a/addons/mail/models/res_config_settings.py +++ b/addons/mail/models/res_config_settings.py @@ -3,8 +3,6 @@ import datetime -from werkzeug import urls - from odoo import api, fields, models, tools diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index f7f043cad3c..e9bae2de172 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -1,15 +1,11 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import logging - from odoo import _, api, fields, models, tools from odoo.addons.bus.models.bus_presence import AWAY_TIMER from odoo.addons.bus.models.bus_presence import DISCONNECTION_TIMER from odoo.osv import expression -_logger = logging.getLogger(__name__) - class Partner(models.Model): """ Update partner to add a field about notification preferences. Add a generic opt-out field that can be used @@ -18,12 +14,12 @@ class Partner(models.Model): _inherit = ['res.partner', 'mail.activity.mixin', 'mail.thread.blacklist'] _mail_flat_thread = False + # override to add tracking email = fields.Char(tracking=1) phone = fields.Char(tracking=2) - - channel_ids = fields.Many2many('mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id', string='Channels', copy=False) - # override the field to track the visibility of user user_id = fields.Many2one(tracking=True) + # channels + channel_ids = fields.Many2many('mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id', string='Channels', copy=False) def _compute_im_status(self): super()._compute_im_status() @@ -32,6 +28,31 @@ class Partner(models.Model): if odoobot in self: odoobot.im_status = 'bot' + # pseudo computes + + def _get_needaction_count(self): + """ compute the number of needaction of the current partner """ + self.ensure_one() + self.env['mail.notification'].flush(['is_read', 'res_partner_id']) + self.env.cr.execute(""" + SELECT count(*) as needaction_count + FROM mail_notification R + WHERE R.res_partner_id = %s AND (R.is_read = false OR R.is_read IS NULL)""", (self.id,)) + return self.env.cr.dictfetchall()[0].get('needaction_count') + + def _get_starred_count(self): + """ compute the number of starred of the current partner """ + self.ensure_one() + self.env.cr.execute(""" + SELECT count(*) as starred_count + FROM mail_message_res_partner_starred_rel R + WHERE R.res_partner_id = %s """, (self.id,)) + return self.env.cr.dictfetchall()[0].get('starred_count') + + # ------------------------------------------------------------ + # MESSAGING + # ------------------------------------------------------------ + def _message_get_suggested_recipients(self): recipients = super(Partner, self)._message_get_suggested_recipients() for partner in self: @@ -39,11 +60,18 @@ class Partner(models.Model): return recipients def _message_get_default_recipients(self): - return {r.id: { - 'partner_ids': [r.id], - 'email_to': False, - 'email_cc': False} - for r in self} + return { + r.id: + {'partner_ids': [r.id], + 'email_to': False, + 'email_cc': False + } + for r in self + } + + # ------------------------------------------------------------ + # ORM + # ------------------------------------------------------------ @api.model @api.returns('self', lambda value: value.id) @@ -69,6 +97,10 @@ class Partner(models.Model): create_values['email'] = parsed_email return self.create(create_values) + # ------------------------------------------------------------ + # DISCUSS + # ------------------------------------------------------------ + def mail_partner_format(self): partners_format = dict() for partner in self: @@ -86,25 +118,6 @@ class Partner(models.Model): } return partners_format - def _get_needaction_count(self): - """ compute the number of needaction of the current partner """ - self.ensure_one() - self.env['mail.notification'].flush(['is_read', 'res_partner_id']) - self.env.cr.execute(""" - SELECT count(*) as needaction_count - FROM mail_notification R - WHERE R.res_partner_id = %s AND (R.is_read = false OR R.is_read IS NULL)""", (self.id,)) - return self.env.cr.dictfetchall()[0].get('needaction_count') - - def _get_starred_count(self): - """ compute the number of starred of the current partner """ - self.ensure_one() - self.env.cr.execute(""" - SELECT count(*) as starred_count - FROM mail_message_res_partner_starred_rel R - WHERE R.res_partner_id = %s """, (self.id,)) - return self.env.cr.dictfetchall()[0].get('starred_count') - def _message_fetch_failed(self): """Returns all messages, sent by the current partner, that have errors, in the format expected by the web client.""" diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py index 460d101cc2f..d91cf339801 100644 --- a/addons/mail/models/res_users.py +++ b/addons/mail/models/res_users.py @@ -26,6 +26,10 @@ class Users(models.Model): "- Handle by Emails: notifications are sent to your email address\n" "- Handle in Odoo: notifications appear in your Odoo Inbox") + # ------------------------------------------------------------ + # CRUD + # ------------------------------------------------------------ + @property def SELF_READABLE_FIELDS(self): return super().SELF_READABLE_FIELDS + ['notification_type'] @@ -80,6 +84,10 @@ class Users(models.Model): lambda cp: cp.channel_id.public != 'public' and cp.channel_id.channel_type == 'channel' ).unlink() + # ------------------------------------------------------------ + # DISCUSS + # ------------------------------------------------------------ + def _init_messaging(self): self.ensure_one() partner_root = self.env.ref('base.partner_root')