Files
odoo_source/addons/mail/models/mail_notification.py
T
Sébastien Theys c2918c139b [IMP] web, *: improve mock server and replace most mail mockRPC
Improve mock server:

- add support for mocked `fetch`
- add support for `active_test`
- add support for x2m `in` in domains
- add support for default values computed from a function
- implement a more natural "next id" compute
- allow initial data without ids
- ensure write and x2m commands integrity
- improve bad data/bad commands error messages
- always warn for failing RPC, not only in debug mode
- fix all existing tests that had inconsistency data

Other changes done in mail (or dependents) that are not just related to tests:

- remove `direct_partner` from formatter result
  ->`correspondent` can be computed from other keys, especially `members`

- fix `livechat_visitor` convertData
  -> only process if there is value

- add `current_partner` and `current_user_id` as `init_messaging` result
  -> easier to mock than session

- remove usage of `need_moderation`
  -> that was just a search indirection to `moderation_status`

- adapt `partner_id` -> `res_partner_id` key in `_notification_format`
  -> to be consistent with field name

- add name in result of `mail_partner_format`
  -> sometimes display_name is not the same

- remove usage of `is_moderator`
  -> that was just an indirection to `moderation_channel_ids`

Enterprise counterpart: https://github.com/odoo/enterprise/pull/11523
task-2287171

closes odoo/odoo#55854

X-original-commit: 7ba3fecb3377a720d1eb70e7515a0c45da73836d
Related: odoo/enterprise#12391
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
2020-08-13 16:26:35 +00:00

105 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.tools.translate import _
class MailNotification(models.Model):
_name = 'mail.notification'
_table = 'mail_message_res_partner_needaction_rel'
_rec_name = 'res_partner_id'
_log_access = False
_description = 'Message Notifications'
# origin
mail_message_id = fields.Many2one('mail.message', 'Message', index=True, ondelete='cascade', required=True)
mail_id = fields.Many2one('mail.mail', 'Mail', index=True, help='Optional mail_mail ID. Used mainly to optimize searches.')
# recipient
res_partner_id = fields.Many2one('res.partner', 'Recipient', index=True, ondelete='cascade')
# status
notification_type = fields.Selection([
('inbox', 'Inbox'), ('email', 'Email')
], string='Notification Type', default='inbox', index=True, required=True)
notification_status = fields.Selection([
('ready', 'Ready to Send'),
('sent', 'Sent'),
('bounce', 'Bounced'),
('exception', 'Exception'),
('canceled', 'Canceled')
], string='Status', default='ready', index=True)
is_read = fields.Boolean('Is Read', index=True)
read_date = fields.Datetime('Read Date', copy=False)
failure_type = fields.Selection(selection=[
("SMTP", "Connection failed (outgoing mail server problem)"),
("RECIPIENT", "Invalid email address"),
("BOUNCE", "Email address rejected by destination"),
("UNKNOWN", "Unknown error"),
], string='Failure type')
failure_reason = fields.Text('Failure reason', copy=False)
_sql_constraints = [
# email notification;: partner is required
('notification_partner_required',
"CHECK(notification_type NOT IN ('email', 'inbox') OR res_partner_id IS NOT NULL)",
'Customer is required for inbox / email notification'),
]
def init(self):
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s',
('mail_notification_res_partner_id_is_read_notification_status_mail_message_id',))
if not self._cr.fetchone():
self._cr.execute("""
CREATE INDEX mail_notification_res_partner_id_is_read_notification_status_mail_message_id
ON mail_message_res_partner_needaction_rel (res_partner_id, is_read, notification_status, mail_message_id)
""")
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get('is_read'):
vals['read_date'] = fields.Datetime.now()
return super(MailNotification, self).create(vals_list)
def write(self, vals):
if vals.get('is_read'):
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 = [
('is_read', '=', True),
('read_date', '<', fields.Datetime.now() - relativedelta(days=max_age_days)),
('res_partner_id.partner_share', '=', False),
('notification_status', 'in', ('sent', 'canceled'))
]
return self.search(domain).unlink()
def _filtered_for_web_client(self):
"""Returns only the notifications to show on the web client."""
return self.filtered(lambda n:
n.notification_type != 'inbox' and
(n.notification_status in ['bounce', 'exception', 'canceled'] or n.res_partner_id.partner_share)
)
def _notification_format(self):
"""Returns the current notifications in the format expected by the web
client."""
return [{
'id': notif.id,
'notification_type': notif.notification_type,
'notification_status': notif.notification_status,
'failure_type': notif.failure_type,
'res_partner_id': [notif.res_partner_id.id, notif.res_partner_id.display_name],
} for notif in self]