From 05221788298c9d6f19712f49eb25de917db06f80 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Wed, 25 Nov 2015 10:56:03 +0100 Subject: [PATCH] [ADD] mail_follower_custom_notification --- mail_follower_custom_notification/README.rst | 66 +++++++++++ mail_follower_custom_notification/__init__.py | 5 + .../__openerp__.py | 27 +++++ .../mail_follower_custom_notification.png | Bin 0 -> 8816 bytes .../models/__init__.py | 8 ++ .../models/mail_followers.py | 42 +++++++ .../models/mail_message.py | 25 ++++ .../models/mail_message_subtype.py | 22 ++++ .../models/mail_notification.py | 33 ++++++ .../models/mail_thread.py | 108 ++++++++++++++++++ .../static/description/icon.png | Bin 0 -> 9455 bytes .../css/mail_follower_custom_notification.css | 5 + .../js/mail_follower_custom_notification.js | 79 +++++++++++++ .../xml/mail_follower_custom_notification.xml | 38 ++++++ .../tests/__init__.py | 4 + .../test_mail_follower_custom_notification.py | 75 ++++++++++++ .../views/mail_message_subtype.xml | 18 +++ .../views/templates.xml | 11 ++ .../wizards/__init__.py | 4 + ...ail_subtype_assign_custom_notifications.py | 46 ++++++++ ...il_subtype_assign_custom_notifications.xml | 30 +++++ 21 files changed, 646 insertions(+) create mode 100644 mail_follower_custom_notification/README.rst create mode 100644 mail_follower_custom_notification/__init__.py create mode 100644 mail_follower_custom_notification/__openerp__.py create mode 100644 mail_follower_custom_notification/images/mail_follower_custom_notification.png create mode 100644 mail_follower_custom_notification/models/__init__.py create mode 100644 mail_follower_custom_notification/models/mail_followers.py create mode 100644 mail_follower_custom_notification/models/mail_message.py create mode 100644 mail_follower_custom_notification/models/mail_message_subtype.py create mode 100644 mail_follower_custom_notification/models/mail_notification.py create mode 100644 mail_follower_custom_notification/models/mail_thread.py create mode 100644 mail_follower_custom_notification/static/description/icon.png create mode 100644 mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css create mode 100644 mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js create mode 100644 mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml create mode 100644 mail_follower_custom_notification/tests/__init__.py create mode 100644 mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py create mode 100644 mail_follower_custom_notification/views/mail_message_subtype.xml create mode 100644 mail_follower_custom_notification/views/templates.xml create mode 100644 mail_follower_custom_notification/wizards/__init__.py create mode 100644 mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py create mode 100644 mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml diff --git a/mail_follower_custom_notification/README.rst b/mail_follower_custom_notification/README.rst new file mode 100644 index 00000000..406f160d --- /dev/null +++ b/mail_follower_custom_notification/README.rst @@ -0,0 +1,66 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +========================================== +Custom notification settings for followers +========================================== + +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 +their own messages. + +You can also set defaults for this settings on the subtype in question. + +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 / +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 +===== + +.. 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 `_. + +Credits +======= + +Contributors +------------ + +* Holger Brunn + +Maintainer +---------- + +.. 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. diff --git a/mail_follower_custom_notification/__init__.py b/mail_follower_custom_notification/__init__.py new file mode 100644 index 00000000..968fe660 --- /dev/null +++ b/mail_follower_custom_notification/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models +from . import wizards diff --git a/mail_follower_custom_notification/__openerp__.py b/mail_follower_custom_notification/__openerp__.py new file mode 100644 index 00000000..e15b28ba --- /dev/null +++ b/mail_follower_custom_notification/__openerp__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# © 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", + "author": "Therp BV,Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Social Network", + "summary": "Let followers choose if they want to receive email " + "notifications for a given subscription", + "depends": [ + 'mail', + ], + "data": [ + "wizards/mail_subtype_assign_custom_notifications.xml", + "views/mail_message_subtype.xml", + 'views/templates.xml', + ], + "qweb": [ + 'static/src/xml/mail_follower_custom_notification.xml', + ], + "images": [ + 'images/mail_follower_custom_notification.png', + ], + "installable": True, +} diff --git a/mail_follower_custom_notification/images/mail_follower_custom_notification.png b/mail_follower_custom_notification/images/mail_follower_custom_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..3c63b9a769ec4810e34457cfedd1540e88c9c258 GIT binary patch literal 8816 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 literal 0 HcmV?d00001 diff --git a/mail_follower_custom_notification/models/__init__.py b/mail_follower_custom_notification/models/__init__.py new file mode 100644 index 00000000..b0a8e2ce --- /dev/null +++ b/mail_follower_custom_notification/models/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import mail_followers +from . import mail_thread +from . import mail_message +from . import mail_notification +from . import mail_message_subtype diff --git a/mail_follower_custom_notification/models/mail_followers.py b/mail_follower_custom_notification/models/mail_followers.py new file mode 100644 index 00000000..82719402 --- /dev/null +++ b/mail_follower_custom_notification/models/mail_followers.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import api, fields, models + + +class MailFollowers(models.Model): + _inherit = 'mail.followers' + + force_mail_subtype_ids = fields.Many2many( + 'mail.message.subtype', 'mail_followers_force_mail_rel', + 'mail_followers_id', 'mail_message_subtype_id', + string='Force mails from subtype') + + force_nomail_subtype_ids = fields.Many2many( + 'mail.message.subtype', 'mail_followers_force_nomail_rel', + 'mail_followers_id', 'mail_message_subtype_id', + string='Force no mails from subtype') + + force_own_subtype_ids = fields.Many2many( + 'mail.message.subtype', 'mail_followers_force_own_rel', + 'mail_followers_id', 'mail_message_subtype_id', + 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: + if not subtype.res_model and\ + subtype.custom_notification_model_ids and\ + this.res_model not in\ + subtype.custom_notification_model_ids\ + .mapped('model'): + continue + if subtype.custom_notification_mail == 'force_yes': + this.force_mail_subtype_ids += subtype + if subtype.custom_notification_mail == 'force_no': + this.force_nomail_subtype_ids += subtype + if subtype.custom_notification_own: + this.force_own_subtype_ids += subtype + return this diff --git a/mail_follower_custom_notification/models/mail_message.py b/mail_follower_custom_notification/models/mail_message.py new file mode 100644 index 00000000..6ec41b24 --- /dev/null +++ b/mail_follower_custom_notification/models/mail_message.py @@ -0,0 +1,25 @@ +# -*- 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 MailMessage(models.Model): + _inherit = 'mail.message' + + @api.multi + def _notify(self, force_send=False, 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([ + ('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) + return super(MailMessage, self)._notify( + self.id, force_send=force_send, 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 new file mode 100644 index 00000000..f58e199d --- /dev/null +++ b/mail_follower_custom_notification/models/mail_message_subtype.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import fields, models + + +class MailMessageSubtype(models.Model): + _inherit = 'mail.message.subtype' + + custom_notification_mail = fields.Selection( + [('force_yes', 'Force yes'), ('force_no', 'Force no')], + string='Send mail notification', help='Leave empty to use the ' + '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') + custom_notification_own = fields.Boolean( + 'Notify about own messages', help='Check this to have notifications ' + '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)]) diff --git a/mail_follower_custom_notification/models/mail_notification.py b/mail_follower_custom_notification/models/mail_notification.py new file mode 100644 index 00000000..c70e0f50 --- /dev/null +++ b/mail_follower_custom_notification/models/mail_notification.py @@ -0,0 +1,33 @@ +# -*- 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 new file mode 100644 index 00000000..910eb222 --- /dev/null +++ b/mail_follower_custom_notification/models/mail_thread.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import SUPERUSER_ID, api, models +from openerp.addons.mail.mail_thread import mail_thread + + +class MailThread(models.Model): + _inherit = '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 + + @api.multi + def message_custom_notification_update_user(self, custom_notifications): + """change custom_notifications from user ids to partner ids""" + user2partner = dict( + self.env['res.users'].browse(map(int, custom_notifications.keys())) + .mapped(lambda user: (str(user.id), str(user.partner_id.id))) + ) + return self.message_custom_notification_update({ + user2partner[user_id]: data + for user_id, data in custom_notifications.iteritems() + }) + + @api.multi + def message_custom_notification_update(self, custom_notifications): + """custom_notifications is a dictionary with partner ids as keys + 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())) + + custom_notifications = { + int(key): value + for key, value in custom_notifications.iteritems() + if key != 'False' + } + + for follower in self.env['mail.followers'].search([ + ('res_model', '=', self._name), + ('res_id', 'in', self.ids), + ('partner_id', 'in', custom_notifications.keys()), + ]): + data = custom_notifications[follower.partner_id.id] + follower.write({ + 'force_mail_subtype_ids': [(6, 0, ids_with_value( + data, 'force_mail', 'force_yes'))], + 'force_nomail_subtype_ids': [(6, 0, ids_with_value( + data, 'force_mail', 'force_no'))], + 'force_own_subtype_ids': [(6, 0, ids_with_value( + data, 'force_own', '1'))] + }), + + def _register_hook(self, cr): + model_ids = self.pool['ir.model'].search(cr, SUPERUSER_ID, []) + rebuilt = [] + for model in self.pool['ir.model'].browse(cr, SUPERUSER_ID, model_ids): + if model.model not in self.pool: + continue + model_object = self.pool[model.model] + if not isinstance(model_object, mail_thread): + continue + if isinstance(model_object, MailThread): + continue + bases = list(model_object.__class__.__bases__) + if MailThread not in bases: + bases.insert(1, MailThread) + class_dict = dict(model_object.__dict__) + class_dict['_inherit'] = model_object._name + new_model_class = type(model_object._name, tuple(bases), + class_dict) + new_model = new_model_class._build_model(self.pool, cr) + self.pool.models[model.model] = new_model + new_model._prepare_setup(cr, SUPERUSER_ID) + new_model._setup_base(cr, SUPERUSER_ID, False) + new_model._setup_fields(cr, SUPERUSER_ID) + rebuilt.append(new_model) + for model in rebuilt: + model._setup_complete(cr, SUPERUSER_ID) + return super(MailThread, self)._register_hook(cr) diff --git a/mail_follower_custom_notification/static/description/icon.png b/mail_follower_custom_notification/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 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 new file mode 100644 index 00000000..92b9ecb9 --- /dev/null +++ b/mail_follower_custom_notification/static/src/css/mail_follower_custom_notification.css @@ -0,0 +1,5 @@ +.oe_custom_notification legend +{ + font-size: inherit; + margin-bottom: 0px; +} 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 new file mode 100644 index 00000000..104342b1 --- /dev/null +++ b/mail_follower_custom_notification/static/src/js/mail_follower_custom_notification.js @@ -0,0 +1,79 @@ +//-*- 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; + } + $list.empty(); + this._super(data, id, dialog); + $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')); + }); + 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(); + } + */ + 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) + { + update_func = 'message_custom_notification_update'; + follower_ids = [user_pid]; + oe_action = jQuery('.oe_edit_actions'); + } + _(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')), + settings = follower_settings[id] = {}; + settings['force_mail'] = jQuery(this) + .find('.oe_custom_notification_mail input:checked') + .val(); + settings['force_own'] = jQuery(this) + .find('.oe_custom_notification_own input:checked') + .val(); + }); + }); + return jQuery.when(this._super.apply(this, arguments)) + .then(function() + { + return self.ds_model.call( + update_func, + [[self.view.datarecord.id], custom_notifications]) + }) + }, + }); +} 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 new file mode 100644 index 00000000..25fee159 --- /dev/null +++ b/mail_follower_custom_notification/static/src/xml/mail_follower_custom_notification.xml @@ -0,0 +1,38 @@ + + diff --git a/mail_follower_custom_notification/tests/__init__.py b/mail_follower_custom_notification/tests/__init__.py new file mode 100644 index 00000000..ef042795 --- /dev/null +++ b/mail_follower_custom_notification/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import test_mail_follower_custom_notification 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 new file mode 100644 index 00000000..11bed947 --- /dev/null +++ b/mail_follower_custom_notification/tests/test_mail_follower_custom_notification.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp.tests.common import TransactionCase + + +class TestMailFollowerCustomNotification(TransactionCase): + 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') + followed_partner_demo = followed_partner.sudo(demo_user.id) + followed_partner_demo.message_subscribe_users() + + # 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) + + # 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): { + 'force_mail': 'force_yes', + 'force_own': '1', + }, + }, + }) + # 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) + + # post a message and see if we successfully forced a notification to + # ourselves + 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) + + # 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')]) + 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) diff --git a/mail_follower_custom_notification/views/mail_message_subtype.xml b/mail_follower_custom_notification/views/mail_message_subtype.xml new file mode 100644 index 00000000..0d60986c --- /dev/null +++ b/mail_follower_custom_notification/views/mail_message_subtype.xml @@ -0,0 +1,18 @@ + + + + + mail.message.subtype + + + + + + + + + + + + + diff --git a/mail_follower_custom_notification/views/templates.xml b/mail_follower_custom_notification/views/templates.xml new file mode 100644 index 00000000..fbfbec8b --- /dev/null +++ b/mail_follower_custom_notification/views/templates.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/mail_follower_custom_notification/wizards/__init__.py b/mail_follower_custom_notification/wizards/__init__.py new file mode 100644 index 00000000..e968c053 --- /dev/null +++ b/mail_follower_custom_notification/wizards/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 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 new file mode 100644 index 00000000..c0413e7e --- /dev/null +++ b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# © 2015 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import api, fields, models + + +class MailSubtypeAssignCustomNotifications(models.TransientModel): + _name = 'mail.subtype.assign.custom.notifications' + _description = 'Assign custom notification settings to existing followers' + + subtype_ids = fields.Many2many( + 'mail.message.subtype', 'mail_subtype_assign_custom_notifications_rel', + string='Subtypes', required=True, + default=lambda self: [(6, 0, self.env.context.get('active_ids', []))]) + + @api.multi + def button_apply(self): + self.ensure_one() + for subtype in self.subtype_ids: + domain = [('subtype_ids', '=', subtype.id)] + if subtype.custom_notification_model_ids: + domain.append( + ('res_model', 'in', + subtype.custom_notification_model_ids.mapped('model'))) + self.env['mail.followers'].with_context(active_test=False)\ + .search(domain)\ + .write({ + 'force_mail_subtype_ids': [ + (4, subtype.id) + if subtype.custom_notification_mail == 'force_yes' + else + (3, subtype.id) + ], + 'force_nomail_subtype_ids': [ + (4, subtype.id) + if subtype.custom_notification_mail == 'force_no' + else + (3, subtype.id) + ], + 'force_own_subtype_ids': [ + (4, subtype.id) + if subtype.custom_notification_own + else + (3, subtype.id) + ], + }) 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 new file mode 100644 index 00000000..adbab627 --- /dev/null +++ b/mail_follower_custom_notification/wizards/mail_subtype_assign_custom_notifications.xml @@ -0,0 +1,30 @@ + + + + + mail.subtype.assign.custom.notifications + +
+ + + +
+
+
+
+
+ +
+