mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 08:52:08 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -1,11 +1,12 @@
|
|||
# -*- 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.exceptions import AccessError
|
||||
from odoo.tools.constants import GC_UNLINK_LIMIT
|
||||
from odoo.tools.translate import _
|
||||
from odoo.addons.mail.tools.discuss import Store
|
||||
|
||||
|
||||
class MailNotification(models.Model):
|
||||
|
|
@ -21,16 +22,21 @@ class MailNotification(models.Model):
|
|||
mail_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')
|
||||
# set if no matching partner exists (mass mail)
|
||||
# must be normalized except if notification is cancel/failure from invalid email
|
||||
mail_email_address = fields.Char(help='Recipient email address')
|
||||
# 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'),
|
||||
('process', 'Processing'), # being checked by intermediary like IAP for sms
|
||||
('pending', 'Sent'), # used with SMS; mail does not differentiate sent from delivered
|
||||
('sent', 'Delivered'),
|
||||
('bounce', 'Bounced'),
|
||||
('exception', 'Exception'),
|
||||
('canceled', 'Canceled')
|
||||
('canceled', 'Cancelled')
|
||||
], string='Status', default='ready', index=True)
|
||||
is_read = fields.Boolean('Is Read', index=True)
|
||||
read_date = fields.Datetime('Read Date', copy=False)
|
||||
|
|
@ -38,42 +44,39 @@ class MailNotification(models.Model):
|
|||
# generic
|
||||
("unknown", "Unknown error"),
|
||||
# mail
|
||||
("mail_bounce", "Bounce"),
|
||||
("mail_spam", "Detected As Spam"),
|
||||
("mail_email_invalid", "Invalid email address"),
|
||||
("mail_email_missing", "Missing email address"),
|
||||
("mail_from_invalid", "Invalid from address"),
|
||||
("mail_from_missing", "Missing from address"),
|
||||
("mail_smtp", "Connection failed (outgoing mail server problem)"),
|
||||
], string='Failure type')
|
||||
# mass mode
|
||||
("mail_bl", "Blacklisted Address"),
|
||||
("mail_optout", "Opted Out"),
|
||||
("mail_dup", "Duplicated Email")], 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'),
|
||||
]
|
||||
_notification_partner_required = models.Constraint(
|
||||
"CHECK(notification_type != 'inbox' OR res_partner_id IS NOT NULL)",
|
||||
'Customer is required for inbox notification',
|
||||
)
|
||||
_notification_partner_or_email_required = models.Constraint(
|
||||
"CHECK(notification_type != 'email' OR failure_type IS NOT NULL OR res_partner_id IS NOT NULL OR COALESCE(mail_email_address, '') != '')",
|
||||
'Customer or email is required for inbox / email notification',
|
||||
)
|
||||
_res_partner_id_is_read_notification_status_mail_message_id = models.Index("(res_partner_id, is_read, notification_status, mail_message_id)")
|
||||
_author_id_notification_status_failure = models.Index("(author_id, notification_status) WHERE notification_status IN ('bounce', 'exception')")
|
||||
_unique_mail_message_id_res_partner_id_ = models.UniqueIndex("(mail_message_id, res_partner_id) WHERE res_partner_id IS NOT NULL")
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def init(self):
|
||||
self._cr.execute("""
|
||||
CREATE INDEX IF NOT EXISTS mail_notification_res_partner_id_is_read_notification_status_mail_message_id
|
||||
ON mail_notification (res_partner_id, is_read, notification_status, mail_message_id);
|
||||
CREATE INDEX IF NOT EXISTS mail_notification_author_id_notification_status_failure
|
||||
ON mail_notification (author_id, notification_status)
|
||||
WHERE notification_status IN ('bounce', 'exception');
|
||||
""")
|
||||
self.env.cr.execute(
|
||||
"""CREATE UNIQUE INDEX IF NOT EXISTS unique_mail_message_id_res_partner_id_if_set
|
||||
ON %s (mail_message_id, res_partner_id)
|
||||
WHERE res_partner_id IS NOT NULL""" % self._table
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
messages = self.env['mail.message'].browse(vals['mail_message_id'] for vals in vals_list)
|
||||
messages.check_access_rights('read')
|
||||
messages.check_access_rule('read')
|
||||
messages.check_access('read')
|
||||
for vals in vals_list:
|
||||
if vals.get('is_read'):
|
||||
vals['read_date'] = fields.Datetime.now()
|
||||
|
|
@ -94,10 +97,9 @@ class MailNotification(models.Model):
|
|||
('res_partner_id.partner_share', '=', False),
|
||||
('notification_status', 'in', ('sent', 'canceled'))
|
||||
]
|
||||
records = self.search(domain, limit=models.GC_UNLINK_LIMIT)
|
||||
if len(records) >= models.GC_UNLINK_LIMIT:
|
||||
self.env.ref('base.autovacuum_job')._trigger()
|
||||
return records.unlink()
|
||||
records = self.search(domain, limit=GC_UNLINK_LIMIT)
|
||||
records.unlink()
|
||||
return len(records), len(records) == GC_UNLINK_LIMIT # done, remaining
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TOOLS
|
||||
|
|
@ -108,7 +110,9 @@ class MailNotification(models.Model):
|
|||
if self.failure_type != 'unknown':
|
||||
return dict(self._fields['failure_type'].selection).get(self.failure_type, _('No Error'))
|
||||
else:
|
||||
return _("Unknown error") + ": %s" % (self.failure_reason or '')
|
||||
if self.failure_reason:
|
||||
return _("Unknown error: %(error)s", error=self.failure_reason)
|
||||
return _("Unknown error")
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# DISCUSS
|
||||
|
|
@ -118,20 +122,26 @@ class MailNotification(models.Model):
|
|||
"""Returns only the notifications to show on the web client."""
|
||||
def _filter_unimportant_notifications(notif):
|
||||
if notif.notification_status in ['bounce', 'exception', 'canceled'] \
|
||||
or notif.res_partner_id.partner_share:
|
||||
or notif.res_partner_id.partner_share or notif.mail_email_address:
|
||||
return True
|
||||
subtype = notif.mail_message_id.subtype_id
|
||||
return not subtype or subtype.track_recipients
|
||||
|
||||
return self.filtered(_filter_unimportant_notifications)
|
||||
|
||||
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] if notif.res_partner_id else False,
|
||||
} for notif in self]
|
||||
def _to_store_defaults(self, target):
|
||||
return [
|
||||
"mail_email_address",
|
||||
"failure_type",
|
||||
"mail_message_id",
|
||||
"notification_status",
|
||||
"notification_type",
|
||||
Store.One(
|
||||
"res_partner_id",
|
||||
[
|
||||
"name",
|
||||
"email",
|
||||
Store.Attr("display_name", predicate=lambda p: not p.name),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue