From 31c1eff584b4184591890d62a6ed1a0f46053fec Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Thu, 28 Mar 2019 17:52:12 +0100 Subject: [PATCH] [MIG] mail_follower_custom_notification to v10 --- mail_follower_custom_notification/README.rst | 88 ++-- mail_follower_custom_notification/__init__.py | 3 +- .../{__openerp__.py => __manifest__.py} | 4 +- .../controllers/__init__.py | 4 + .../controllers/mail_controller.py | 29 ++ .../models/__init__.py | 5 +- .../models/base_patch_models_mixin.py | 92 ---- .../models/mail_followers.py | 5 +- .../models/mail_message.py | 23 +- .../models/mail_message_subtype.py | 16 +- .../models/mail_notification.py | 33 -- .../models/mail_thread.py | 42 +- .../models/res_partner.py | 30 ++ .../readme/CONFIGURE.rst | 10 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/CREDITS.rst | 1 + .../readme/DESCRIPTION.rst | 6 + .../static/description/index.html | 442 ++++++++++++++++++ .../css/mail_follower_custom_notification.css | 15 +- .../js/mail_follower_custom_notification.js | 98 ++-- .../xml/mail_follower_custom_notification.xml | 63 ++- .../test_mail_follower_custom_notification.py | 86 ++-- .../views/mail_message_subtype.xml | 30 +- .../views/templates.xml | 18 +- .../wizards/__init__.py | 2 +- ...ail_subtype_assign_custom_notifications.py | 5 +- ...il_subtype_assign_custom_notifications.xml | 55 ++- 27 files changed, 802 insertions(+), 404 deletions(-) rename mail_follower_custom_notification/{__openerp__.py => __manifest__.py} (91%) create mode 100644 mail_follower_custom_notification/controllers/__init__.py create mode 100644 mail_follower_custom_notification/controllers/mail_controller.py delete mode 100644 mail_follower_custom_notification/models/base_patch_models_mixin.py delete mode 100644 mail_follower_custom_notification/models/mail_notification.py create mode 100644 mail_follower_custom_notification/models/res_partner.py create mode 100644 mail_follower_custom_notification/readme/CONFIGURE.rst create mode 100644 mail_follower_custom_notification/readme/CONTRIBUTORS.rst create mode 100644 mail_follower_custom_notification/readme/CREDITS.rst create mode 100644 mail_follower_custom_notification/readme/DESCRIPTION.rst create mode 100644 mail_follower_custom_notification/static/description/index.html diff --git a/mail_follower_custom_notification/README.rst b/mail_follower_custom_notification/README.rst index 7f14c572..b03244ad 100644 --- a/mail_follower_custom_notification/README.rst +++ b/mail_follower_custom_notification/README.rst @@ -1,73 +1,97 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :alt: License: AGPL-3 - ========================================== Custom notification settings for followers ========================================== +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github + :target: https://github.com/OCA/social/tree/10.0/mail_follower_custom_notification + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-10-0/social-10-0-mail_follower_custom_notification + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/205/10.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + In standard Odoo, receiving mail notifications is an all or nothing affair. -This module allows you users to decide per followed record if they want to -receive emails or not. Further, they can choose to receive notification about +This module allows users to decide per followed record if they want to +receive emails or not. Further, they can choose to receive notifications about their own messages. You can also set defaults for this settings on the subtype in question. +**Table of contents** + +.. contents:: + :local: + Configuration ============= When followers open their subscriptions, they will be offered the choice to override mail settings and to force being notified about their own messages. -You can add defaults per message sub type for this settings in Settings / +Note subscriptions are only editable for users of the `Technical settings` +group. + +You can add defaults per message subtype for this settings in Settings / Technical / Email / Subtypes. Here, you also have the opportunity to apply those defaults to existing subscriptions. Note that this overrides all customizations your users already have done. -Usage -===== - -To use this module, for example you need to: - -- Go to Sales -> Sales -> Customers -- Go Inside any customer and in the right-botton corner press "Follow" button -- Unfold Following menu and check new functionality with "mail notificacions" - - -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/205/8.0 - -For further information, please visit: - -* https://www.odoo.com/forum/help-1 - Bug Tracker =========== Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed feedback -`here `_. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. Credits ======= +Authors +~~~~~~~ + +* Therp BV + Contributors ------------- +~~~~~~~~~~~~ * Holger Brunn -Maintainer ----------- +Other credits +~~~~~~~~~~~~~ + +* Odoo Community Association: `Icon `_. + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. +This module is part of the `OCA/social `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_follower_custom_notification/__init__.py b/mail_follower_custom_notification/__init__.py index 968fe660..b12f44cb 100644 --- a/mail_follower_custom_notification/__init__.py +++ b/mail_follower_custom_notification/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import models from . import wizards +from . import controllers diff --git a/mail_follower_custom_notification/__openerp__.py b/mail_follower_custom_notification/__manifest__.py similarity index 91% rename from mail_follower_custom_notification/__openerp__.py rename to mail_follower_custom_notification/__manifest__.py index e15b28ba..1318c648 100644 --- a/mail_follower_custom_notification/__openerp__.py +++ b/mail_follower_custom_notification/__manifest__.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Custom notification settings for followers", - "version": "8.0.1.0.0", + "version": "10.0.1.0.0", "author": "Therp BV,Odoo Community Association (OCA)", "license": "AGPL-3", "category": "Social Network", diff --git a/mail_follower_custom_notification/controllers/__init__.py b/mail_follower_custom_notification/controllers/__init__.py new file mode 100644 index 00000000..20777a6f --- /dev/null +++ b/mail_follower_custom_notification/controllers/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Therp BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from . import mail_controller diff --git a/mail_follower_custom_notification/controllers/mail_controller.py b/mail_follower_custom_notification/controllers/mail_controller.py new file mode 100644 index 00000000..359c4926 --- /dev/null +++ b/mail_follower_custom_notification/controllers/mail_controller.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Therp BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import http +from odoo.http import request +from odoo.addons.mail.controllers.main import MailController as _MailController + + +class MailController(_MailController): + @http.route() + def read_subscription_data(self, res_model, follower_id): + """Add custom notification data to subscriptions""" + subtypes_list = super(MailController, self).read_subscription_data( + res_model, follower_id, + ) + follower = request.env['mail.followers'].browse(follower_id) + for subtype_dict in subtypes_list: + subtype = request.env['mail.message.subtype'].browse( + subtype_dict['id'] + ) + subtype_dict['force_mail'] = 'default' + if subtype in follower.force_mail_subtype_ids: + subtype_dict['force_mail'] = 'force_yes' + elif subtype in follower.force_nomail_subtype_ids: + subtype_dict['force_mail'] = 'force_no' + subtype_dict['force_own'] = ( + subtype in follower.force_own_subtype_ids + ) + return subtypes_list diff --git a/mail_follower_custom_notification/models/__init__.py b/mail_follower_custom_notification/models/__init__.py index 507fec24..4702885e 100644 --- a/mail_follower_custom_notification/models/__init__.py +++ b/mail_follower_custom_notification/models/__init__.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import base_patch_models_mixin from . import mail_followers from . import mail_thread from . import mail_message -from . import mail_notification from . import mail_message_subtype +from . import res_partner diff --git a/mail_follower_custom_notification/models/base_patch_models_mixin.py b/mail_follower_custom_notification/models/base_patch_models_mixin.py deleted file mode 100644 index 21ea5e68..00000000 --- a/mail_follower_custom_notification/models/base_patch_models_mixin.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2016 Therp BV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -import logging -from openerp import models - - -_logger = logging.getLogger(__file__) - - -# TODO: this should be a helper module to cetralize the point of failure -# in case this introduces tacit bugs -class BasePatchModelsMixin(models.AbstractModel): - """ - This is a mixin class meant to simplify working with patches - on BaseModel or on abstract models like mail.thread. - If you just change them, models created earlier will lack the - attributes you add. Just inherit from this mixin, it will check - which existing models need your changes and apply them. - - In your module, do something like - - class MailThread(models.AbstractModel): - _name = 'mail.thread' - _inherit = ['base.patch.models.mixin', 'mail.thread'] - - in case you need to patch BaseModel, say - - class BaseModel(models.BaseModel): - _name = 'my.unique.model.name' - _inherit = 'base.patch.models.mixin' - - Your code will behave as if it was an inherited class of the class you pass - in the second parameter to _base_patch_models. - """ - _name = 'base.patch.models.mixin' - - def _base_patch_models(self, cr, our_class=None, parent_class=None): - """iterate through existing models to apply our changes there if - necessary""" - if self._name == BasePatchModelsMixin._name: - return - my_bases = self.__class__.__bases__ - for i in range(max(len(my_bases) - 1, 0)): - if my_bases[i]._name == BasePatchModelsMixin._name: - our_class = my_bases[i - 1] - parent_class = my_bases[i + 1] - inherit = [self._inherit]\ - if isinstance(self._inherit, basestring) else self._inherit - for i in range(len(my_bases) - 1, 0, -1): - # this can be different from the above if our mixin is used - # multiple times on the same model - if my_bases[i]._name in inherit: - parent_class = my_bases[i] - break - if self.__class__.__bases__[-1] == BasePatchModelsMixin\ - and not our_class or not parent_class: - our_class = self.__class__.__bases__[-2] - parent_class = models.BaseModel - if not our_class or not parent_class: - _logger.info( - 'Failed to autodetect own class or parent class for %s, ' - 'ignoring', self._name) - return - - for model_name, model_object in self.pool.models.iteritems(): - if not isinstance(model_object, parent_class): - continue - if isinstance(model_object, our_class): - continue - if not isinstance(model_object, models.Model): - continue - bases = list(model_object.__class__.__bases__) - position = 1 - if parent_class == models.BaseModel: - position = len(bases) - else: - for i in range(len(bases) - 1, position, -1): - if bases[i]._name in inherit: - position = i - break - bases.insert(position, our_class) - model_object.__class__.__bases__ = tuple(bases) - - def _register_hook(self, cr): - self._base_patch_models(cr) - for base in self.__class__.__bases__: - if not hasattr(super(base, self), '_register_hook'): - return - if super(base, self)._register_hook != self._register_hook: - return super(base, self)._register_hook.__func__( - super(base, self), cr) diff --git a/mail_follower_custom_notification/models/mail_followers.py b/mail_follower_custom_notification/models/mail_followers.py index 82719402..ef096f46 100644 --- a/mail_follower_custom_notification/models/mail_followers.py +++ b/mail_follower_custom_notification/models/mail_followers.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, fields, models +from odoo import api, fields, models class MailFollowers(models.Model): @@ -23,7 +23,6 @@ class MailFollowers(models.Model): string='Force own mails from subtype') @api.model - @api.returns('self', lambda x: x.id) def create(self, values): this = super(MailFollowers, self).create(values) for subtype in this.subtype_ids: diff --git a/mail_follower_custom_notification/models/mail_message.py b/mail_follower_custom_notification/models/mail_message.py index 6ec41b24..9132c252 100644 --- a/mail_follower_custom_notification/models/mail_message.py +++ b/mail_follower_custom_notification/models/mail_message.py @@ -1,25 +1,28 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, models +from odoo import api, models class MailMessage(models.Model): _inherit = 'mail.message' @api.multi - def _notify(self, force_send=False, user_signature=True): + def _notify( + self, force_send=False, send_after_commit=True, user_signature=True, + ): """notify author if she's a follower and turned on force_own""" self.ensure_one() - if self.subtype_id and self.model and self.res_id: - author_follower = self.env['mail.followers'].search([ + if self.subtype_id and self.model and self.res_id and self.env[ + 'mail.followers' + ].search([ ('res_model', '=', self.model), ('res_id', '=', self.res_id), ('partner_id', '=', self.author_id.id), ('force_own_subtype_ids', '=', self.subtype_id.id), - ]) - self.env['mail.notification']._notify( - self.id, partners_to_notify=author_follower.partner_id.ids, - force_send=force_send, user_signature=user_signature) + ]): + self = self.with_context(mail_notify_author=True) return super(MailMessage, self)._notify( - self.id, force_send=force_send, user_signature=user_signature) + force_send=force_send, send_after_commit=send_after_commit, + user_signature=user_signature, + ) diff --git a/mail_follower_custom_notification/models/mail_message_subtype.py b/mail_follower_custom_notification/models/mail_message_subtype.py index f58e199d..72c475b8 100644 --- a/mail_follower_custom_notification/models/mail_message_subtype.py +++ b/mail_follower_custom_notification/models/mail_message_subtype.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import fields, models +from odoo import fields, models class MailMessageSubtype(models.Model): @@ -9,14 +9,18 @@ class MailMessageSubtype(models.Model): custom_notification_mail = fields.Selection( [('force_yes', 'Force yes'), ('force_no', 'Force no')], - string='Send mail notification', help='Leave empty to use the ' + string='Send mail notification', help='Leave empty to use the setting ' 'on the partner\'s form, set to "Force yes" to always send messages ' 'of this type via email, and "Force no" to never send messages of ' - 'type via email') + 'type via email', + ) custom_notification_own = fields.Boolean( 'Notify about own messages', help='Check this to have notifications ' - 'generated and sent via email about own messages') + 'generated and sent via email about own messages', + ) custom_notification_model_ids = fields.Many2many( 'ir.model', string='Models', help='Choose for which models the ' 'custom configuration applies. This is only necessary if your subtype ' - 'doesn\'t set a model itself', domain=[('osv_memory', '=', False)]) + 'doesn\'t set a model itself', + domain=[('transient', '=', False)], + ) diff --git a/mail_follower_custom_notification/models/mail_notification.py b/mail_follower_custom_notification/models/mail_notification.py deleted file mode 100644 index c70e0f50..00000000 --- a/mail_follower_custom_notification/models/mail_notification.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2015 Therp BV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, models - - -class MailNotification(models.Model): - _inherit = 'mail.notification' - - @api.multi - def get_partners_to_email(self, message): - partner_ids = super(MailNotification, self)\ - .get_partners_to_email(message) - for this in self: - follower = self.env['mail.followers'].search([ - ('res_model', '=', message.model), - ('res_id', '=', message.res_id), - ('partner_id', '=', this.partner_id.id), - '|', '|', - ('force_nomail_subtype_ids', '=', message.subtype_id.id), - ('force_mail_subtype_ids', '=', message.subtype_id.id), - ('force_own_subtype_ids', '=', message.subtype_id.id), - ]) - if not follower: - continue - if (message.subtype_id in follower.force_mail_subtype_ids or - message.subtype_id in follower.force_own_subtype_ids) and\ - this.partner_id.id not in partner_ids: - partner_ids.append(this.partner_id.id) - if message.subtype_id in follower.force_nomail_subtype_ids and\ - this.partner_id.id in partner_ids: - partner_ids.remove(this.partner_id.id) - return partner_ids diff --git a/mail_follower_custom_notification/models/mail_thread.py b/mail_follower_custom_notification/models/mail_thread.py index 11c23eb8..1a890ee8 100644 --- a/mail_follower_custom_notification/models/mail_thread.py +++ b/mail_follower_custom_notification/models/mail_thread.py @@ -1,40 +1,11 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, models +from odoo import api, models class MailThread(models.AbstractModel): - _inherit = ['base.patch.models.mixin', 'mail.thread'] - _name = 'mail.thread' - - @api.multi - def _get_subscription_data(self, name, args, user_pid=None): - result = super(MailThread, self)._get_subscription_data( - name, args, user_pid=user_pid) - subtypes = self.env['mail.message.subtype'].search([ - ('hidden', '=', False), - '|', - ('res_model', '=', self._name), - ('res_model', '=', False), - ]) - for follower in self.env['mail.followers'].search([ - ('res_model', '=', self._name), - ('res_id', 'in', result.keys()), - ('partner_id', '=', user_pid or self.env.user.partner_id.id), - ]): - # values are ordered dicts, so we get the correct matches - for subtype, data in zip( - subtypes, - result[follower.res_id]['message_subtype_data'].values()): - data['force_mail'] = 'default' - if subtype in follower.force_mail_subtype_ids: - data['force_mail'] = 'force_yes' - elif subtype in follower.force_nomail_subtype_ids: - data['force_mail'] = 'force_no' - data['force_own'] =\ - subtype in follower.force_own_subtype_ids - return result + _inherit = 'mail.thread' @api.multi def message_custom_notification_update_user(self, custom_notifications): @@ -54,9 +25,10 @@ class MailThread(models.AbstractModel): and dictionaries mapping message subtype ids to custom notification values""" def ids_with_value(data, key, value): - return map(lambda x: int(x[0]), - filter(lambda x: x[1][key] == value, - data.iteritems())) + return map( + lambda x: int(x[0]), + filter(lambda x: x[1][key] == value, data.iteritems()) + ) custom_notifications = { int(key): value diff --git a/mail_follower_custom_notification/models/res_partner.py b/mail_follower_custom_notification/models/res_partner.py new file mode 100644 index 00000000..304fbd2a --- /dev/null +++ b/mail_follower_custom_notification/models/res_partner.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Therp BV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import api, models + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + @api.multi + def _notify_by_email( + self, message, force_send=False, send_after_commit=True, + user_signature=True, + ): + """remove partners from `self` who requested not to be mailed, + add the ones who did the opposite""" + domain = [ + ('res_model', '=', message.model), + ('res_id', '=', message.res_id), + ] + self |= self.env['mail.followers'].search( + domain + [('force_mail_subtype_ids', '=', message.subtype_id.id)] + ).mapped('partner_id') + self -= self.env['mail.followers'].search( + domain + [('force_nomail_subtype_ids', '=', message.subtype_id.id)] + ).mapped('partner_id') + return super(ResPartner, self)._notify_by_email( + message, force_send=force_send, + send_after_commit=send_after_commit, user_signature=user_signature, + ) diff --git a/mail_follower_custom_notification/readme/CONFIGURE.rst b/mail_follower_custom_notification/readme/CONFIGURE.rst new file mode 100644 index 00000000..95b051ee --- /dev/null +++ b/mail_follower_custom_notification/readme/CONFIGURE.rst @@ -0,0 +1,10 @@ +When followers open their subscriptions, they will be offered the choice to +override mail settings and to force being notified about their own messages. + +Note subscriptions are only editable for users of the `Technical settings` +group. + +You can add defaults per message subtype for this settings in Settings / +Technical / Email / Subtypes. Here, you also have the opportunity to apply +those defaults to existing subscriptions. Note that this overrides all +customizations your users already have done. diff --git a/mail_follower_custom_notification/readme/CONTRIBUTORS.rst b/mail_follower_custom_notification/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..b120a956 --- /dev/null +++ b/mail_follower_custom_notification/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Holger Brunn diff --git a/mail_follower_custom_notification/readme/CREDITS.rst b/mail_follower_custom_notification/readme/CREDITS.rst new file mode 100644 index 00000000..cc056a80 --- /dev/null +++ b/mail_follower_custom_notification/readme/CREDITS.rst @@ -0,0 +1 @@ +* Odoo Community Association: `Icon `_. diff --git a/mail_follower_custom_notification/readme/DESCRIPTION.rst b/mail_follower_custom_notification/readme/DESCRIPTION.rst new file mode 100644 index 00000000..6d1d1d14 --- /dev/null +++ b/mail_follower_custom_notification/readme/DESCRIPTION.rst @@ -0,0 +1,6 @@ +In standard Odoo, receiving mail notifications is an all or nothing affair. +This module allows users to decide per followed record if they want to +receive emails or not. Further, they can choose to receive notifications about +their own messages. + +You can also set defaults for this settings on the subtype in question. diff --git a/mail_follower_custom_notification/static/description/index.html b/mail_follower_custom_notification/static/description/index.html new file mode 100644 index 00000000..59101d8e --- /dev/null +++ b/mail_follower_custom_notification/static/description/index.html @@ -0,0 +1,442 @@ + + + + + + +Custom notification settings for followers + + + +
+

Custom notification settings for followers

+ + +

Beta License: AGPL-3 OCA/social Translate me on Weblate Try me on Runbot

+

In standard Odoo, receiving mail notifications is an all or nothing affair. +This module allows users to decide per followed record if they want to +receive emails or not. Further, they can choose to receive notifications about +their own messages.

+

You can also set defaults for this settings on the subtype in question.

+

Table of contents

+ +
+

Configuration

+

When followers open their subscriptions, they will be offered the choice to +override mail settings and to force being notified about their own messages.

+

Note subscriptions are only editable for users of the Technical settings +group.

+

You can add defaults per message subtype for this settings in Settings / +Technical / Email / Subtypes. Here, you also have the opportunity to apply +those defaults to existing subscriptions. Note that this overrides all +customizations your users already have done.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Therp BV
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+
    +
  • Odoo Community Association: Icon.
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/social project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css b/mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css index 92b9ecb9..a75b9021 100644 --- a/mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css +++ b/mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css @@ -1,5 +1,18 @@ -.oe_custom_notification legend +.o_mail_follower_custom_notification +{ + padding: 5px 10px 10px 10px; +} +.o_mail_follower_custom_notification fieldset > legend { font-size: inherit; margin-bottom: 0px; } +.o_mail_follower_custom_notification fieldset > div, +.o_mail_follower_custom_notification fieldset > div > label +{ + white-space: nowrap; +} +.o_mail_follower_custom_notification fieldset > div > label +{ + font-weight: normal; +} diff --git a/mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js b/mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js index 104342b1..449e3d1e 100644 --- a/mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js +++ b/mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js @@ -1,79 +1,65 @@ -//-*- coding: utf-8 -*- -//© 2015 Therp BV -//License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -openerp.mail_follower_custom_notification = function(instance) -{ - instance.mail_followers.Followers.include({ - display_subtypes: function(data, id, dialog) - { - var $list = this.$('.oe_subtype_list ul'); - if (dialog) - { - $list = this.$dialog.$el; +// -*- coding: utf-8 -*- +// Copyright 2015-2019 Therp BV +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +odoo.define('mail_follower_custom_notification', function(require) { + 'use strict'; + var core = require('web.core'); + require('mail.Followers'); + core.form_widget_registry.get('mail_followers').include({ + /* eslint-disable-next-line no-unused-vars */ + display_subtypes:function (data, dialog, display_warning) { + this._super.apply(this, arguments); + var $list = this.$('ul.o_followers_list'); + if (dialog) { + $list = this.dialog.$('ul'); } - $list.empty(); - this._super(data, id, dialog); - $list.find('input[type=checkbox]').change(function() - { + $list.find('input[type=checkbox]').change(function() { $list.find(_.str.sprintf( '#custom_notification_%s%s', jQuery(this).data('id'), dialog ? '_dialog' : '' - )) - .toggle(jQuery(this).prop('checked')); + )).toggle(jQuery(this).prop('checked')); }); - if(!dialog) - { - $list.find('.oe_custom_notification input[type=radio]') - .change(this.proxy('do_update_subscription')); - }; - }, - do_update_subscription: function(event, user_pid) - { - /* - if(jQuery(event.currentTarget).parents('.oe_custom_notification') - .length) - { - // mail reacts on all inputs, suppress for our inputs - return jQuery.when(); + if (!dialog) { + $list.find( + '.oe_custom_notification input[type=radio]' + ).change(this.proxy('do_update_subscription')); } - */ + }, + /* eslint-disable-next-line no-unused-vars */ + do_update_subscription: function (event, follower_id, is_channel) { var self = this, update_func = 'message_custom_notification_update_user', follower_ids = [this.session.uid], custom_notifications = {}, - oe_action = this.$('.oe_actions'); - if(user_pid) - { + $list = this.$('ul'); + if (follower_id !== undefined) { update_func = 'message_custom_notification_update'; - follower_ids = [user_pid]; - oe_action = jQuery('.oe_edit_actions'); + follower_ids = [follower_id]; + $list = this.dialog.$('ul'); } - _(follower_ids).each(function(follower) - { - + _(follower_ids).each(function(follower) { var follower_settings = custom_notifications[follower] = {}; - oe_action.find('.oe_custom_notification') - .each(function() - { - var id = parseInt(jQuery(this).data('id')), + $list.find( + '.o_mail_follower_custom_notification' + ).each(function () { + var id = parseInt(jQuery(this).data('id'), 10), settings = follower_settings[id] = {}; - settings['force_mail'] = jQuery(this) - .find('.oe_custom_notification_mail input:checked') + settings.force_mail = jQuery(this) + .find('.mail input:checked') .val(); - settings['force_own'] = jQuery(this) - .find('.oe_custom_notification_own input:checked') + settings.force_own = jQuery(this) + .find('.own input:checked') .val(); }); }); - return jQuery.when(this._super.apply(this, arguments)) - .then(function() - { + return jQuery.when( + this._super.apply(this, arguments) + ).then(function () { return self.ds_model.call( update_func, - [[self.view.datarecord.id], custom_notifications]) - }) + [[self.view.datarecord.id], custom_notifications]); + }).then(this.proxy('render_value')); }, }); -} +}); diff --git a/mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml b/mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml index 25fee159..72f184f2 100644 --- a/mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml +++ b/mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml @@ -1,38 +1,35 @@ diff --git a/mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py b/mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py index 11bed947..62463bd6 100644 --- a/mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py +++ b/mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py @@ -1,33 +1,48 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from mock import Mock, patch from openerp.tests.common import TransactionCase +from ..controllers.mail_controller import MailController class TestMailFollowerCustomNotification(TransactionCase): + def _call_controller(self, res_model, follower_id): + mt_comment = self.env.ref('mail.mt_comment') + with patch('__builtin__.super') as mock_super, patch( + 'odoo.addons.mail_follower_custom_notification.controllers.' + 'mail_controller.request' + ) as mock_request: + mock_super.return_value = Mock( + read_subscription_data=lambda res_model, follower_id: [{ + 'id': mt_comment.id, + }], + ) + mock_request.env = self.env + return MailController.read_subscription_data.__func__( + None, res_model, follower_id, + )[0] + def test_mail_follower_custom_notification(self): - self.env['mail.thread']._register_hook() followed_partner = self.env['res.partner'].create({ 'name': 'I\'m followed', }) demo_user = self.env.ref('base.user_demo') + mt_comment = self.env.ref('mail.mt_comment') followed_partner_demo = followed_partner.sudo(demo_user.id) followed_partner_demo.message_subscribe_users() + follower = followed_partner_demo.message_follower_ids.filtered( + lambda x: x.partner_id == demo_user.partner_id + ) # see if default subscriptions return default custom settings - subscription_data = followed_partner_demo._get_subscription_data( - None, None) - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_mail'], - 'default') - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_own'], - False) + subscription_data = self._call_controller( + follower.res_model, follower.id, + ) + self.assertEqual(subscription_data['force_mail'], 'default') + self.assertEqual(subscription_data['force_own'], False) # set custom settings - mt_comment = self.env.ref('mail.mt_comment') followed_partner_demo.message_custom_notification_update_user({ str(demo_user.id): { str(mt_comment.id): { @@ -37,39 +52,34 @@ class TestMailFollowerCustomNotification(TransactionCase): }, }) # see if we can read them back - subscription_data = followed_partner_demo._get_subscription_data( - None, None) - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_mail'], - 'force_yes') - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_own'], - True) + subscription_data = self._call_controller( + follower.res_model, follower.id, + ) + self.assertEqual(subscription_data['force_mail'], 'force_yes') + self.assertEqual(subscription_data['force_own'], True) # post a message and see if we successfully forced a notification to # ourselves + # pylint: disable=translation-required followed_partner_demo.message_post('hello world', subtype='mt_comment') - self.assertEqual( - followed_partner_demo.message_ids[:-1].notification_ids.partner_id, - demo_user.partner_id) + self.assertIn( + demo_user.partner_id, + followed_partner_demo.message_ids[:-1].notification_ids.mapped( + 'res_partner_id', + ) + ) # assign default values on message subtype and apply them to all # followers - mt_comment.custom_notification_model_ids = self.env['ir.model']\ - .search([('model', '=', 'res.partner')]) + mt_comment.custom_notification_model_ids = self.env['ir.model'].search( + [('model', '=', 'res.partner')] + ) wizard = self.env['mail.subtype.assign.custom.notifications']\ .with_context(active_ids=mt_comment.ids)\ .create({}) wizard.button_apply() - subscription_data = followed_partner_demo._get_subscription_data( - None, None) - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_mail'], - 'default') - self.assertEqual( - subscription_data[followed_partner.id]['message_subtype_data'] - ['Discussions']['force_own'], - False) + subscription_data = self._call_controller( + follower.res_model, follower.id, + ) + self.assertEqual(subscription_data['force_mail'], 'default') + self.assertEqual(subscription_data['force_own'], False) diff --git a/mail_follower_custom_notification/views/mail_message_subtype.xml b/mail_follower_custom_notification/views/mail_message_subtype.xml index 0d60986c..c43a5d07 100644 --- a/mail_follower_custom_notification/views/mail_message_subtype.xml +++ b/mail_follower_custom_notification/views/mail_message_subtype.xml @@ -1,18 +1,16 @@ - - - - mail.message.subtype - - - - - - - - + + + mail.message.subtype + + + + + + + - - - - + + + + diff --git a/mail_follower_custom_notification/views/templates.xml b/mail_follower_custom_notification/views/templates.xml index fbfbec8b..f24f9214 100644 --- a/mail_follower_custom_notification/views/templates.xml +++ b/mail_follower_custom_notification/views/templates.xml @@ -1,11 +1,9 @@ - - - - - + + + diff --git a/mail_follower_custom_notification/wizards/__init__.py b/mail_follower_custom_notification/wizards/__init__.py index e968c053..5b4f1fb7 100644 --- a/mail_follower_custom_notification/wizards/__init__.py +++ b/mail_follower_custom_notification/wizards/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import mail_subtype_assign_custom_notifications diff --git a/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py index c0413e7e..66d04092 100644 --- a/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py +++ b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Therp BV +# Copyright 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import api, fields, models @@ -15,8 +15,7 @@ class MailSubtypeAssignCustomNotifications(models.TransientModel): @api.multi def button_apply(self): - self.ensure_one() - for subtype in self.subtype_ids: + for subtype in self.mapped('subtype_ids'): domain = [('subtype_ids', '=', subtype.id)] if subtype.custom_notification_model_ids: domain.append( diff --git a/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml index adbab627..8264c344 100644 --- a/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml +++ b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml @@ -1,30 +1,27 @@ - - - - mail.subtype.assign.custom.notifications - -
- - - -
-
-
-
-
- -
-
+ + + mail.subtype.assign.custom.notifications + +
+ + + +
+
+
+
+
+ +