diff --git a/mail_private/__init__.py b/mail_private/__init__.py index cde864b..aa40758 100644 --- a/mail_private/__init__.py +++ b/mail_private/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- +# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html) from . import models diff --git a/mail_private/__manifest__.py b/mail_private/__manifest__.py index 6c0e421..36720c3 100644 --- a/mail_private/__manifest__.py +++ b/mail_private/__manifest__.py @@ -1,10 +1,18 @@ # -*- coding: utf-8 -*- +# Copyright 2016 x620 +# Copyright 2016 Ilmir Karamov +# Copyright 2016 Ivan Yelizariev +# Copyright 2017 Artyom Losev +# Copyright 2018 Ruslan Ronzhin +# Copyright 2018 Kolushov Alexandr +# Copyright 2019 Artem Rafailov +# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html). { "name": """Internal Messaging""", "summary": """Send private messages to specified recipients, regardless of who are in followers list.""", "category": "Discuss", "images": ['images/mail_private_image.png'], - "version": "10.0.1.0.1", + "version": "10.0.1.1.0", "application": False, "author": "IT-Projects LLC, Pavel Romanchenko", diff --git a/mail_private/doc/changelog.rst b/mail_private/doc/changelog.rst index f3b7c08..01b747c 100644 --- a/mail_private/doc/changelog.rst +++ b/mail_private/doc/changelog.rst @@ -1,3 +1,9 @@ +`1.1.0` +------- + +- **New**: added ability to select channels for private message sending. +- **New**: internal users are flagged automatically. + `1.0.1` ------- diff --git a/mail_private/full_composer_wizard.xml b/mail_private/full_composer_wizard.xml index 9f57a20..46daeb5 100644 --- a/mail_private/full_composer_wizard.xml +++ b/mail_private/full_composer_wizard.xml @@ -1,4 +1,8 @@ + + diff --git a/mail_private/models.py b/mail_private/models.py index 1f69756..33d4520 100644 --- a/mail_private/models.py +++ b/mail_private/models.py @@ -1,4 +1,10 @@ # -*- coding: utf-8 -*- +# Copyright 2016 x620 +# Copyright 2016 manawi +# Copyright 2017 Artyom Losev +# Copyright 2019 Artem Rafailov +# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html). + from odoo import models, fields, api @@ -7,8 +13,75 @@ class MailComposeMessage(models.TransientModel): is_private = fields.Boolean(string='Send Internal Message') + def get_internal_users_ids(self): + internal_users_ids = self.env['res.users'].search([('share', '=', False)]).ids + return internal_users_ids + @api.multi def send_mail(self, auto_commit=False): for w in self: w.is_log = True if w.is_private else w.is_log super(MailComposeMessage, self).send_mail(auto_commit=False) + + +class MailMessage(models.Model): + _inherit = 'mail.message' + + @api.multi + def _notify(self, force_send=False, send_after_commit=True, user_signature=True): + self_sudo = self.sudo() + if 'is_private' not in self_sudo._context or not self_sudo._context['is_private']: + super(MailMessage, self)._notify(force_send, send_after_commit, user_signature) + else: + self._notify_mail_private(force_send, send_after_commit, user_signature) + + @api.multi + def _notify_mail_private(self, force_send=False, send_after_commit=True, user_signature=True): + """ The method was partially copied from Odoo. + In the current method, the way of getting channels for a private message is changed. + """ + # have a sudoed copy to manipulate partners (public can go here with + # website modules like forum / blog / ... + + # TDE CHECK: add partners / channels as arguments to be able to notify a message with / without computation ?? + self.ensure_one() # tde: not sure, just for testinh, will see + + partners = self.env['res.partner'] | self.partner_ids + channels = self.env['mail.channel'] | self.channel_ids + + # update message, with maybe custom values + message_values = { + 'channel_ids': [(6, 0, channels.ids)], + 'needaction_partner_ids': [(6, 0, partners.ids)] + } + if self.model and self.res_id and hasattr(self.env[self.model], 'message_get_message_notify_values'): + message_values.update( + self.env[self.model].browse(self.res_id).message_get_message_notify_values(self, message_values)) + self.write(message_values) + + # notify partners and channels + partners._notify(self, force_send=force_send, send_after_commit=send_after_commit, + user_signature=user_signature) + channels._notify(self) + + # Discard cache, because child / parent allow reading and therefore + # change access rights. + if self.parent_id: + self.parent_id.invalidate_cache() + + return True + + +class MailThread(models.AbstractModel): + _inherit = 'mail.thread' + + @api.multi + @api.returns('self', lambda value: value.id) + def message_post(self, body='', subject=None, message_type='notification', + subtype=None, parent_id=False, attachments=None, + content_subtype='html', **kwargs): + if 'channel_ids' in kwargs: + kwargs['channel_ids'] = [(4, pid) for pid in kwargs['channel_ids']] + return super(MailThread, self).message_post(body, subject, message_type, + subtype, parent_id, attachments, + content_subtype, **kwargs) diff --git a/mail_private/static/src/js/mail_private.js b/mail_private/static/src/js/mail_private.js index d311b3c..7204585 100644 --- a/mail_private/static/src/js/mail_private.js +++ b/mail_private/static/src/js/mail_private.js @@ -1,3 +1,9 @@ +/* Copyright 2016 x620 + Copyright 2016 Ivan Yelizariev + Copyright 2016 manawi + Copyright 2017 Artyom Losev + Copyright 2019 Artem Rafailov + License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html). */ odoo.define('mail_private', function (require) { 'use strict'; @@ -22,6 +28,7 @@ Chatter.include({ var self = this; if (this.private) { message.subtype = false; + message.channel_ids = this.get_checked_channels_ids(); } var options = {model: this.model, res_id: this.res_id}; chat_manager.post_message(message, options).then( @@ -33,32 +40,38 @@ Chatter.include({ }).fail(function () { // todo: display notification }); - }, + }, on_open_composer_private_message: function (event) { var self = this; this.private = true; this.get_recipients_for_internal_message().then(function (data) { self.recipients_for_internal_message = data; - self.open_composer({is_private: true}); + return self.get_channels_for_internal_message(); + }).then(function (data) { + self.channels_for_internal_message = data; + self.get_internal_users_ids().then(function(res_ids){ + self.open_composer({is_private: true, internal_ids: res_ids}); + }); }); }, on_open_composer_new_message: function () { this._super.apply(this, arguments); this.private = false; + this.context.is_private = false; }, open_composer: function (options) { var self = this; this._super.apply(this, arguments); if (options && options.is_private) { - + self.internal_users_ids = options.internal_ids; this.composer.options.is_private = options.is_private; _.each(self.recipients_for_internal_message, function (partner) { self.composer.suggested_partners.push({ - checked: (partner.user_ids.length > 0), + checked: _.intersection(self.internal_users_ids, partner.user_ids).length > 0, partner_id: partner.id, full_name: partner.name, name: partner.name, @@ -68,6 +81,15 @@ Chatter.include({ :'Follower' }); }); + + _.each(self.channels_for_internal_message, function (channel) { + self.composer.suggested_channels.push({ + checked: true, + channel_id: channel.id, + full_name: channel.name, + name: ('# ' + channel.name), + }); + }); } }, @@ -101,13 +123,68 @@ Chatter.include({ }); }); }); - } + }, + + get_channels_for_internal_message: function () { + var self = this; + self.result = {}; + return new Model(this.context.default_model).query( + ['message_follower_ids', 'partner_id']).filter( + [['id', '=', self.context.default_res_id]]).all() + .then(function (thread) { + var follower_ids = thread[0].message_follower_ids; + self.result[self.context.default_res_id] = []; + self.customer = thread[0].partner_id; + + // Fetch channels ids + return new Model('mail.followers').call( + 'read', [follower_ids, ['channel_id']]).then(function (res_channels) { + // Filter result and push to array + var res_channels_filtered = _.map(res_channels, function (channel) { + if (channel.channel_id[0]) { + return channel.channel_id[0]; + } + }).filter(function (channel) { + return typeof channel !== 'undefined'; + }); + + return new Model('mail.channel').call( + 'read', [res_channels_filtered, ['name', 'id']] + ).then(function (recipients) { + return recipients; + }); + }); + }); + }, + + get_internal_users_ids: function () { + var ResUser = new Model('mail.compose.message'); + this.users_ids = ResUser.call('get_internal_users_ids', [[]]).then( function (users_ids) { + return users_ids; + }); + return this.users_ids; + }, + + get_checked_channels_ids: function () { + var self = this; + var checked_channels = []; + this.$('.o_composer_suggested_channels input:checked').each(function() { + var full_name = $(this).data('fullname').toString(); + _.each(self.channels_for_internal_message, function(item) { + if (full_name === item.name) { + checked_channels.push(item.id); + } + }); + }); + return checked_channels; + }, }); MailComposer.include({ init: function (parent, dataset, options) { this._super(parent, dataset, options); this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients'; + this.suggested_channels = []; }, @@ -115,6 +192,17 @@ MailComposer.include({ this.$('.o_composer_suggested_partners input:checked').each(function() { $(this).prop('checked', false); }); + this.$('.o_composer_suggested_channels input:checked').each(function() { + $(this).prop('checked', false); + }); + }, + + preprocess_message: function () { + var self = this; + if (self.options.is_private) { + self.context.is_private = true; + } + return this._super(); }, on_open_full_composer: function() { diff --git a/mail_private/static/src/xml/mail_private.xml b/mail_private/static/src/xml/mail_private.xml index 5607c9e..cebfd85 100644 --- a/mail_private/static/src/xml/mail_private.xml +++ b/mail_private/static/src/xml/mail_private.xml @@ -1,4 +1,10 @@ +