From 578858706206ce28c1eb8f84b29b9807b4f527fe Mon Sep 17 00:00:00 2001 From: Jordi Ballester Alomar Date: Tue, 27 Nov 2018 09:35:55 +0100 Subject: [PATCH 01/81] [ADD] mail_activity_team --- mail_activity_team/README.rst | 98 ++++ mail_activity_team/__init__.py | 1 + mail_activity_team/__manifest__.py | 23 + mail_activity_team/models/__init__.py | 3 + mail_activity_team/models/mail_activity.py | 34 ++ .../models/mail_activity_team.py | 14 + mail_activity_team/models/res_users.py | 11 + mail_activity_team/readme/CONTRIBUTORS.rst | 3 + mail_activity_team/readme/DESCRIPTION.rst | 3 + mail_activity_team/readme/USAGE.rst | 17 + .../security/ir.model.access.csv | 4 + .../security/mail_activity_team_security.xml | 15 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 419 ++++++++++++++++++ .../views/mail_activity_team_views.xml | 90 ++++ .../views/mail_activity_views.xml | 70 +++ mail_activity_team/views/res_users_views.xml | 16 + 17 files changed, 821 insertions(+) create mode 100644 mail_activity_team/README.rst create mode 100644 mail_activity_team/__init__.py create mode 100644 mail_activity_team/__manifest__.py create mode 100644 mail_activity_team/models/__init__.py create mode 100644 mail_activity_team/models/mail_activity.py create mode 100644 mail_activity_team/models/mail_activity_team.py create mode 100644 mail_activity_team/models/res_users.py create mode 100644 mail_activity_team/readme/CONTRIBUTORS.rst create mode 100644 mail_activity_team/readme/DESCRIPTION.rst create mode 100644 mail_activity_team/readme/USAGE.rst create mode 100644 mail_activity_team/security/ir.model.access.csv create mode 100644 mail_activity_team/security/mail_activity_team_security.xml create mode 100644 mail_activity_team/static/description/icon.png create mode 100644 mail_activity_team/static/description/index.html create mode 100644 mail_activity_team/views/mail_activity_team_views.xml create mode 100644 mail_activity_team/views/mail_activity_views.xml create mode 100644 mail_activity_team/views/res_users_views.xml diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst new file mode 100644 index 000000000..0c79d92e1 --- /dev/null +++ b/mail_activity_team/README.rst @@ -0,0 +1,98 @@ +================== +Mail Activity Team +================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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/11.0/mail_activity_team + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-11-0/social-11-0-mail_activity_team + :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/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds the possibility to assign teams to activities. + + + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To set up new teams: + +#. Go to *Settings / Activate developer mode* +#. Go to *Settings / Technical / Email / Activity Teams* +#. Create a new Team and assign (optionally) the models in which it will + be used, and the members of the team. + +You can also assign a user to Activity teams going to +*Settings / Users & Companies / Users*, and in the *Preferences* tab, field +Activity Teams. + +When you create a new activity the application will propose the user's +assigned team. + +You can report on the activities assigned to a team going to +*Dashboards / Activities*, and then filter by a specific team or group by +teams. + +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 +~~~~~~~ + +* Eficent + +Contributors +~~~~~~~~~~~~ + +* `Eficent `_: + + * Jordi Ballester Alomar (jordi.ballester@eficent.com) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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_activity_team/__init__.py b/mail_activity_team/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/mail_activity_team/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py new file mode 100644 index 000000000..4963644fb --- /dev/null +++ b/mail_activity_team/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'Mail Activity Team', + 'summary': 'Add Teams to Activities', + 'version': '11.0.1.0.0', + 'development_status': 'Beta', + 'category': 'Social Network', + 'website': 'https://github.com/OCA/social', + 'author': 'Eficent, Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'installable': True, + 'depends': [ + 'mail_activity_board', + ], + 'data': [ + 'security/ir.model.access.csv', + 'security/mail_activity_team_security.xml', + 'views/mail_activity_team_views.xml', + 'views/mail_activity_views.xml', + 'views/res_users_views.xml', + ], +} diff --git a/mail_activity_team/models/__init__.py b/mail_activity_team/models/__init__.py new file mode 100644 index 000000000..2f37e6ccd --- /dev/null +++ b/mail_activity_team/models/__init__.py @@ -0,0 +1,3 @@ +from . import mail_activity_team +from . import mail_activity +from . import res_users diff --git a/mail_activity_team/models/mail_activity.py b/mail_activity_team/models/mail_activity.py new file mode 100644 index 000000000..51cf198f8 --- /dev/null +++ b/mail_activity_team/models/mail_activity.py @@ -0,0 +1,34 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, models, fields + + +class MailActivity(models.Model): + _inherit = "mail.activity" + + def _get_default_team_id(self): + res_model = self.env.context.get('default_res_model', False) + model = self.env['ir.model'].search([('model', '=', res_model)], + limit=1) + domain = [('member_ids', 'in', [self.env.uid])] + if res_model: + domain.extend(['|', ('res_model_ids', '=', False), + ('res_model_ids', 'in', model.ids)]) + return self.env['mail.activity.team'].search(domain, limit=1) + + team_id = fields.Many2one('mail.activity.team', + default=lambda s: s._get_default_team_id(),) + + @api.onchange('res_model_id', 'user_id') + def _onchange_model_user(self): + res = {'domain': {'team_id': []}} + if self.team_id: + if self.user_id not in self.team_id.member_ids: + self.team_id = False + if self.res_model_id: + res['domain']['team_id'] = [ + ('res_model_ids', 'in', self.res_model_id.ids)] + if self.user_id: + res['domain']['team_id'] = [ + ('member_ids', 'in', self.user_id.ids)] + return res diff --git a/mail_activity_team/models/mail_activity_team.py b/mail_activity_team/models/mail_activity_team.py new file mode 100644 index 000000000..81d0676f6 --- /dev/null +++ b/mail_activity_team/models/mail_activity_team.py @@ -0,0 +1,14 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class MailActivityTeam(models.Model): + _name = "mail.activity.team" + _description = 'Mail Activity Team' + + name = fields.Char(string='Name', required=True, translate=True) + active = fields.Boolean(string='Active', default=True) + res_model_ids = fields.Many2many('ir.model', string='Used models') + member_ids = fields.Many2many('res.users', 'mail_activity_team_users_rel', + string="Team Members") diff --git a/mail_activity_team/models/res_users.py b/mail_activity_team/models/res_users.py new file mode 100644 index 000000000..b55ae842f --- /dev/null +++ b/mail_activity_team/models/res_users.py @@ -0,0 +1,11 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import models, fields + + +class ResUsers(models.Model): + _inherit = "res.users" + + activity_team_ids = fields.Many2many('mail.activity.team', + 'mail_activity_team_users_rel', + string="Activity Teams") diff --git a/mail_activity_team/readme/CONTRIBUTORS.rst b/mail_activity_team/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..3507ebd1f --- /dev/null +++ b/mail_activity_team/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Eficent `_: + + * Jordi Ballester Alomar (jordi.ballester@eficent.com) diff --git a/mail_activity_team/readme/DESCRIPTION.rst b/mail_activity_team/readme/DESCRIPTION.rst new file mode 100644 index 000000000..c0a2e3ae1 --- /dev/null +++ b/mail_activity_team/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This module adds the possibility to assign teams to activities. + + diff --git a/mail_activity_team/readme/USAGE.rst b/mail_activity_team/readme/USAGE.rst new file mode 100644 index 000000000..a9b4344f8 --- /dev/null +++ b/mail_activity_team/readme/USAGE.rst @@ -0,0 +1,17 @@ +To set up new teams: + +#. Go to *Settings / Activate developer mode* +#. Go to *Settings / Technical / Email / Activity Teams* +#. Create a new Team and assign (optionally) the models in which it will + be used, and the members of the team. + +You can also assign a user to Activity teams going to +*Settings / Users & Companies / Users*, and in the *Preferences* tab, field +Activity Teams. + +When you create a new activity the application will propose the user's +assigned team. + +You can report on the activities assigned to a team going to +*Dashboards / Activities*, and then filter by a specific team or group by +teams. diff --git a/mail_activity_team/security/ir.model.access.csv b/mail_activity_team/security/ir.model.access.csv new file mode 100644 index 000000000..c5efccfc9 --- /dev/null +++ b/mail_activity_team/security/ir.model.access.csv @@ -0,0 +1,4 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_mail_activity_team_all,mail.activity.team.all,model_mail_activity_team,,1,0,0,0 +access_mail_activity_team_user,mail.activity.team.user,model_mail_activity_team,base.group_user,1,1,0,0 +access_mail_activity_team_system_user,mail.activity.team.system.user,model_mail_activity_team,base.group_system_user,1,1,1,1 diff --git a/mail_activity_team/security/mail_activity_team_security.xml b/mail_activity_team/security/mail_activity_team_security.xml new file mode 100644 index 000000000..9ac63631b --- /dev/null +++ b/mail_activity_team/security/mail_activity_team_security.xml @@ -0,0 +1,15 @@ + + + + + mail.activity: user: my team + + ['|', '&'('team_id', '=', False),('user_id', '=', user.id),('team_id', '=', user.team_ids.ids)] + + + + + + + + diff --git a/mail_activity_team/static/description/icon.png b/mail_activity_team/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_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html new file mode 100644 index 000000000..8862473c6 --- /dev/null +++ b/mail_activity_team/static/description/index.html @@ -0,0 +1,419 @@ + + + + + + +Mail Activity Team + + + +
+

Mail Activity Team

+ + +

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

+

This module adds the possibility to assign teams to activities.

+

Table of contents

+ +
+

Usage

+

To set up new teams:

+
    +
  1. Go to Settings / Activate developer mode
  2. +
  3. Go to Settings / Technical / Email / Activity Teams
  4. +
  5. Create a new Team and assign (optionally) the models in which it will +be used, and the members of the team.
  6. +
+

You can also assign a user to Activity teams going to +Settings / Users & Companies / Users, and in the Preferences tab, field +Activity Teams.

+

When you create a new activity the application will propose the user’s +assigned team.

+

You can report on the activities assigned to a team going to +Dashboards / Activities, and then filter by a specific team or group by +teams.

+
+
+

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

+
    +
  • Eficent
  • +
+
+
+

Contributors

+ +
+
+

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_activity_team/views/mail_activity_team_views.xml b/mail_activity_team/views/mail_activity_team_views.xml new file mode 100644 index 000000000..52203d2dd --- /dev/null +++ b/mail_activity_team/views/mail_activity_team_views.xml @@ -0,0 +1,90 @@ + + + + + + + + mail.activity.team.view.form + mail.activity.team + +
+ +
+ +
+ + + + + + + + + + + + + +
+
+
+
+ + + + + mail.activity.team.view.tree + mail.activity.team + + + + + + + + + + + + mail.activity.team.view.search + mail.activity.team + + + + + + + + + + + + + Activity Teams + mail.activity.team + form + tree,form + [] + {} + + + + + + + +
diff --git a/mail_activity_team/views/mail_activity_views.xml b/mail_activity_team/views/mail_activity_views.xml new file mode 100644 index 000000000..93ad71b91 --- /dev/null +++ b/mail_activity_team/views/mail_activity_views.xml @@ -0,0 +1,70 @@ + + + + + mail.activity.view.form.popup + mail.activity + + + + + + + + + + mail.activity.view.tree + mail.activity + + + + + + + + + + mail.activity.view.form + mail.activity + + + + + + + + + + mail.activity.boards.view.kanban + mail.activity + + + + + + +
+
+ Team: +
+
+
+
+ + + + mail.activity.boards.view.search + mail.activity + + + + + + + + + + + + +
diff --git a/mail_activity_team/views/res_users_views.xml b/mail_activity_team/views/res_users_views.xml new file mode 100644 index 000000000..bf79365e4 --- /dev/null +++ b/mail_activity_team/views/res_users_views.xml @@ -0,0 +1,16 @@ + + + + + res.users.form.activity.team + res.users + + + + + + + + + + From 24e843c7b634480ef08986ef812431fade0b5b4b Mon Sep 17 00:00:00 2001 From: mreficent Date: Tue, 27 Nov 2018 12:22:49 +0100 Subject: [PATCH 02/81] [IMP] Some improvements and fixes --- mail_activity_team/models/mail_activity.py | 70 ++++++++++++++----- .../models/mail_activity_team.py | 69 ++++++++++++++++-- mail_activity_team/models/res_users.py | 8 ++- .../security/ir.model.access.csv | 2 +- .../security/mail_activity_team_security.xml | 4 +- .../views/mail_activity_team_views.xml | 16 +++-- 6 files changed, 134 insertions(+), 35 deletions(-) diff --git a/mail_activity_team/models/mail_activity.py b/mail_activity_team/models/mail_activity.py index 51cf198f8..46dd6de29 100644 --- a/mail_activity_team/models/mail_activity.py +++ b/mail_activity_team/models/mail_activity.py @@ -1,34 +1,66 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, models, fields +from odoo import api, models, fields, _ +from odoo.exceptions import ValidationError class MailActivity(models.Model): _inherit = "mail.activity" - def _get_default_team_id(self): - res_model = self.env.context.get('default_res_model', False) - model = self.env['ir.model'].search([('model', '=', res_model)], - limit=1) - domain = [('member_ids', 'in', [self.env.uid])] + def _get_default_team_id(self, user_id=None): + if not user_id: + user_id = self.env.uid + res_model = self.env.context.get('default_res_model') + model = self.env['ir.model'].search( + [('model', '=', res_model)], limit=1) + domain = [('member_ids', 'in', [user_id])] if res_model: domain.extend(['|', ('res_model_ids', '=', False), ('res_model_ids', 'in', model.ids)]) return self.env['mail.activity.team'].search(domain, limit=1) - team_id = fields.Many2one('mail.activity.team', - default=lambda s: s._get_default_team_id(),) + team_id = fields.Many2one( + comodel_name='mail.activity.team', + default=lambda s: s._get_default_team_id(), + ) - @api.onchange('res_model_id', 'user_id') - def _onchange_model_user(self): + @api.onchange('user_id') + def _onchange_user_id(self): res = {'domain': {'team_id': []}} - if self.team_id: - if self.user_id not in self.team_id.member_ids: - self.team_id = False - if self.res_model_id: - res['domain']['team_id'] = [ - ('res_model_ids', 'in', self.res_model_id.ids)] - if self.user_id: - res['domain']['team_id'] = [ - ('member_ids', 'in', self.user_id.ids)] + if not self.user_id: + return res + res['domain']['team_id'] = [ + '|', + ('res_model_ids', '=', False), + ('res_model_ids', 'in', self.res_model_id.ids)] + if self.team_id and self.user_id in self.team_id.member_ids: + return res + self.team_id = self.with_context( + default_res_model=self.res_model_id.id).\ + _get_default_team_id(user_id=self.user_id.id) return res + + @api.onchange('team_id') + def _onchange_team_id(self): + res = {'domain': {'user_id': []}} + if not self.team_id: + return res + res['domain']['user_id'] = [('id', 'in', self.team_id.member_ids.ids)] + if self.user_id and self.user_id in self.team_id.member_ids: + return res + if self.team_id.user_id: + self.user_id = self.team_id.user_id + elif self.env.user in self.team_id.member_ids.ids: + self.user_id = self.env.user + else: + self.user_id = self.env['res.users'] + return res + + @api.multi + @api.constrains('team_id', 'user_id') + def _check_team_and_user(self): + for activity in self: + if activity.team_id and activity.user_id and \ + activity.user_id not in self.team_id.member_ids: + raise ValidationError( + _('The assigned user is not member of the team.')) diff --git a/mail_activity_team/models/mail_activity_team.py b/mail_activity_team/models/mail_activity_team.py index 81d0676f6..f97c185b5 100644 --- a/mail_activity_team/models/mail_activity_team.py +++ b/mail_activity_team/models/mail_activity_team.py @@ -1,14 +1,71 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models +from odoo import api, fields, models class MailActivityTeam(models.Model): _name = "mail.activity.team" _description = 'Mail Activity Team' - name = fields.Char(string='Name', required=True, translate=True) - active = fields.Boolean(string='Active', default=True) - res_model_ids = fields.Many2many('ir.model', string='Used models') - member_ids = fields.Many2many('res.users', 'mail_activity_team_users_rel', - string="Team Members") + @api.depends('res_model_ids', 'member_ids') + def _compute_missing_activities(self): + activity_model = self.env['mail.activity'] + for team in self: + domain = [('team_id', '=', False)] + if team.member_ids: + domain.append(('user_id', 'in', team.member_ids.ids)) + if team.res_model_ids: + domain.append(('res_model_id', 'in', team.res_model_ids.ids)) + team.count_missing_activities = activity_model.search( + domain, count=True) + + name = fields.Char( + string='Name', + required=True, + translate=True, + ) + active = fields.Boolean( + string='Active', + default=True, + ) + res_model_ids = fields.Many2many( + comodel_name='ir.model', + string='Used models', + domain=lambda self: [ + ('model', 'in', + [k for k in self.env.registry if issubclass( + type(self.env[k]), type(self.env['mail.activity.mixin'])) + and self.env[k]._auto]) + ], + ) + member_ids = fields.Many2many( + comodel_name='res.users', + relation='mail_activity_team_users_rel', + string="Team Members", + ) + user_id = fields.Many2one( + comodel_name='res.users', + string='Team Leader', + domain="[('id', 'in', member_ids)]", + ) + count_missing_activities = fields.Integer( + string="Missing Activities", + compute='_compute_missing_activities', + default=0, + ) + + @api.onchange('member_ids') + def _onchange_member_ids(self): + if self.user_id and self.user_id not in self.member_ids: + self.user_id = False + + def assign_team_to_unassigned_activities(self): + activity_model = self.env['mail.activity'] + for team in self: + domain = [('team_id', '=', False)] + if team.member_ids: + domain.append(('user_id', 'in', team.member_ids.ids)) + if team.res_model_ids: + domain.append(('res_model_id', 'in', team.res_model_ids.ids)) + missing_activities = activity_model.search(domain) + missing_activities.write({'team_id': team.id}) diff --git a/mail_activity_team/models/res_users.py b/mail_activity_team/models/res_users.py index b55ae842f..e1f9cc33a 100644 --- a/mail_activity_team/models/res_users.py +++ b/mail_activity_team/models/res_users.py @@ -6,6 +6,8 @@ class ResUsers(models.Model): _inherit = "res.users" - activity_team_ids = fields.Many2many('mail.activity.team', - 'mail_activity_team_users_rel', - string="Activity Teams") + activity_team_ids = fields.Many2many( + comodel_name='mail.activity.team', + relation='mail_activity_team_users_rel', + string="Activity Teams", + ) diff --git a/mail_activity_team/security/ir.model.access.csv b/mail_activity_team/security/ir.model.access.csv index c5efccfc9..0a9918d68 100644 --- a/mail_activity_team/security/ir.model.access.csv +++ b/mail_activity_team/security/ir.model.access.csv @@ -1,4 +1,4 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" access_mail_activity_team_all,mail.activity.team.all,model_mail_activity_team,,1,0,0,0 access_mail_activity_team_user,mail.activity.team.user,model_mail_activity_team,base.group_user,1,1,0,0 -access_mail_activity_team_system_user,mail.activity.team.system.user,model_mail_activity_team,base.group_system_user,1,1,1,1 +access_mail_activity_team_system_user,mail.activity.team.system.user,model_mail_activity_team,base.group_system,1,1,1,1 diff --git a/mail_activity_team/security/mail_activity_team_security.xml b/mail_activity_team/security/mail_activity_team_security.xml index 9ac63631b..e19398ab2 100644 --- a/mail_activity_team/security/mail_activity_team_security.xml +++ b/mail_activity_team/security/mail_activity_team_security.xml @@ -4,10 +4,10 @@ mail.activity: user: my team - ['|', '&'('team_id', '=', False),('user_id', '=', user.id),('team_id', '=', user.team_ids.ids)] + ["|", ('team_id', 'in', user.activity_team_ids.ids), "&", ('team_id', '=', False), ('user_id', '=', user.id)] - + diff --git a/mail_activity_team/views/mail_activity_team_views.xml b/mail_activity_team/views/mail_activity_team_views.xml index 52203d2dd..72b49a1d9 100644 --- a/mail_activity_team/views/mail_activity_team_views.xml +++ b/mail_activity_team/views/mail_activity_team_views.xml @@ -4,26 +4,34 @@ VIEWS --> - mail.activity.team.view.form mail.activity.team
+
+ +
+ options='{"terminology": "archive"}'/>
+ - + From 9e648aad0f70247e200717c85373bd88fb7102e4 Mon Sep 17 00:00:00 2001 From: mreficent Date: Wed, 28 Nov 2018 14:24:37 +0100 Subject: [PATCH 03/81] [ADD] tests --- mail_activity_team/tests/__init__.py | 1 + .../tests/test_mail_activity_team.py | 118 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 mail_activity_team/tests/__init__.py create mode 100644 mail_activity_team/tests/test_mail_activity_team.py diff --git a/mail_activity_team/tests/__init__.py b/mail_activity_team/tests/__init__.py new file mode 100644 index 000000000..f4a7f5950 --- /dev/null +++ b/mail_activity_team/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mail_activity_team diff --git a/mail_activity_team/tests/test_mail_activity_team.py b/mail_activity_team/tests/test_mail_activity_team.py new file mode 100644 index 000000000..3f7928cbc --- /dev/null +++ b/mail_activity_team/tests/test_mail_activity_team.py @@ -0,0 +1,118 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError + + +class TestMailActivityTeam(TransactionCase): + + def setUp(self): + super(TestMailActivityTeam, self).setUp() + + self.env["mail.activity.team"].search([]).unlink() + + self.employee = self.env['res.users'].create({ + 'company_id': self.env.ref("base.main_company").id, + 'name': "Employee", + 'login': "csu", + 'email': "crmuser@yourcompany.com", + 'groups_id': [(6, 0, [ + self.env.ref('base.group_user').id, + self.env.ref('base.group_partner_manager').id])] + }) + + self.employee2 = self.env['res.users'].create({ + 'company_id': self.env.ref("base.main_company").id, + 'name': "Employee 2", + 'login': "csu2", + 'email': "crmuser2@yourcompany.com", + 'groups_id': [(6, 0, [self.env.ref('base.group_user').id])] + }) + + self.partner_ir_model = self.env['ir.model']._get('res.partner') + + activity_type_model = self.env['mail.activity.type'] + self.activity1 = activity_type_model.create({ + 'name': 'Initial Contact', + 'days': 5, + 'summary': 'ACT 1 : Presentation, barbecue, ... ', + 'res_model_id': self.partner_ir_model.id, + }) + self.activity2 = activity_type_model.create({ + 'name': 'Call for Demo', + 'days': 6, + 'summary': 'ACT 2 : I want to show you my ERP !', + 'res_model_id': self.partner_ir_model.id, + }) + + self.partner_client = self.env.ref("base.res_partner_1") + + self.act1 = self.env['mail.activity'].sudo(self.employee).create({ + 'activity_type_id': self.activity1.id, + 'note': 'Partner activity 1.', + 'res_id': self.partner_client.id, + 'res_model_id': self.partner_ir_model.id, + 'user_id': self.employee.id, + }) + + self.team1 = self.env['mail.activity.team'].sudo().create({ + 'name': 'Team 1', + 'res_model_ids': [(6, 0, [self.partner_ir_model.id])], + 'member_ids': [(6, 0, [self.employee.id])], + }) + + self.team2 = self.env['mail.activity.team'].sudo().create({ + 'name': 'Team 2', + 'res_model_ids': [(6, 0, [self.partner_ir_model.id])], + 'member_ids': [(6, 0, [self.employee.id, self.employee2.id])], + }) + + self.act2 = self.env['mail.activity'].sudo(self.employee).create({ + 'activity_type_id': self.activity2.id, + 'note': 'Partner activity 2.', + 'res_id': self.partner_client.id, + 'res_model_id': self.partner_ir_model.id, + 'user_id': self.employee.id, + }) + + def test_missing_activities(self): + self.assertFalse( + self.act1.team_id, 'Error: Activity 1 should not have a team.') + self.assertEqual(self.team1.count_missing_activities, 1) + self.team1.assign_team_to_unassigned_activities() + self.team1._compute_missing_activities() + self.assertEqual(self.team1.count_missing_activities, 0) + self.assertEqual(self.act1.team_id, self.team1) + + def test_activity_onchanges(self): + self.assertEqual( + self.act2.team_id, self.team1, + 'Error: Activity 2 should have Team 1.') + with self.env.do_in_onchange(): + self.act2.team_id = False + self.act2._onchange_team_id() + self.assertEqual(self.act2.user_id, self.employee) + self.act2.team_id = self.team2 + self.act2._onchange_team_id() + self.assertEqual(self.act2.user_id, self.employee) + self.act2.user_id = self.employee2 + self.act2._onchange_user_id() + self.assertEqual(self.act2.team_id, self.team2) + self.act2.team_id = self.team1 + self.act2._onchange_team_id() + self.assertFalse(self.act2.user_id) + with self.assertRaises(ValidationError): + self.act2.write({ + 'user_id': self.employee2.id, + 'team_id': self.team1.id, + }) + + def test_team_onchanges(self): + self.assertFalse( + self.team2.user_id, + 'Error: Team 2 should not have a Team Leader yet.') + with self.env.do_in_onchange(): + self.team2.user_id = self.employee + self.team2.member_ids = [(3, self.employee.id)] + self.team2._onchange_member_ids() + self.assertFalse(self.team2.user_id) From dd2f4c99bd109dfd92b1f1f017f1cfd8fff20b69 Mon Sep 17 00:00:00 2001 From: mreficent Date: Mon, 3 Dec 2018 13:44:36 +0100 Subject: [PATCH 04/81] [MIG] mail_activity_team: Migration to 12.0 --- mail_activity_team/README.rst | 11 ++++++----- mail_activity_team/__manifest__.py | 2 +- mail_activity_team/readme/CONTRIBUTORS.rst | 1 + mail_activity_team/static/description/index.html | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 0c79d92e1..ae233e3b8 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -14,13 +14,13 @@ Mail Activity Team :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/11.0/mail_activity_team + :target: https://github.com/OCA/social/tree/12.0/mail_activity_team :alt: OCA/social .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/social-11-0/social-11-0-mail_activity_team + :target: https://translation.odoo-community.org/projects/social-12-0/social-12-0-mail_activity_team :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/11.0 + :target: https://runbot.odoo-community.org/runbot/205/12.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -61,7 +61,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -79,6 +79,7 @@ Contributors * `Eficent `_: * Jordi Ballester Alomar (jordi.ballester@eficent.com) + * Miquel Raïch (miquel.raich@eficent.com) Maintainers ~~~~~~~~~~~ @@ -93,6 +94,6 @@ 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. +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_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index 4963644fb..b4f773356 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Mail Activity Team', 'summary': 'Add Teams to Activities', - 'version': '11.0.1.0.0', + 'version': '12.0.1.0.0', 'development_status': 'Beta', 'category': 'Social Network', 'website': 'https://github.com/OCA/social', diff --git a/mail_activity_team/readme/CONTRIBUTORS.rst b/mail_activity_team/readme/CONTRIBUTORS.rst index 3507ebd1f..6bb24056e 100644 --- a/mail_activity_team/readme/CONTRIBUTORS.rst +++ b/mail_activity_team/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `Eficent `_: * Jordi Ballester Alomar (jordi.ballester@eficent.com) + * Miquel Raïch (miquel.raich@eficent.com) diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index 8862473c6..1ee2f86d0 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -345,7 +345,7 @@

Mail Activity Team

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

This module adds the possibility to assign teams to activities.

Table of contents

@@ -383,7 +383,7 @@

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.

+feedback.

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

@@ -410,7 +410,7 @@

Maintainers

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.

+

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.

From 4ce12999029154e86cb2532620cadd3b2a47a33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Gil=20Sorribes?= Date: Fri, 21 Dec 2018 16:05:49 +0100 Subject: [PATCH 05/81] [IMP] Set team responsible as default user when activity is created --- mail_activity_team/models/mail_activity.py | 15 +++++++-------- mail_activity_team/models/mail_activity_team.py | 11 +++++++++-- .../tests/test_mail_activity_team.py | 2 +- .../views/mail_activity_team_views.xml | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/mail_activity_team/models/mail_activity.py b/mail_activity_team/models/mail_activity.py index 46dd6de29..1fccf7463 100644 --- a/mail_activity_team/models/mail_activity.py +++ b/mail_activity_team/models/mail_activity.py @@ -46,14 +46,13 @@ def _onchange_team_id(self): if not self.team_id: return res res['domain']['user_id'] = [('id', 'in', self.team_id.member_ids.ids)] - if self.user_id and self.user_id in self.team_id.member_ids: - return res - if self.team_id.user_id: - self.user_id = self.team_id.user_id - elif self.env.user in self.team_id.member_ids.ids: - self.user_id = self.env.user - else: - self.user_id = self.env['res.users'] + if self.user_id not in self.team_id.member_ids: + if self.team_id.user_id: + self.user_id = self.team_id.user_id + elif len(self.team_id.member_ids) == 1: + self.user_id = self.team_id.member_ids + else: + self.user_id = self.env['res.users'] return res @api.multi diff --git a/mail_activity_team/models/mail_activity_team.py b/mail_activity_team/models/mail_activity_team.py index f97c185b5..1e44e0d7d 100644 --- a/mail_activity_team/models/mail_activity_team.py +++ b/mail_activity_team/models/mail_activity_team.py @@ -46,7 +46,6 @@ def _compute_missing_activities(self): user_id = fields.Many2one( comodel_name='res.users', string='Team Leader', - domain="[('id', 'in', member_ids)]", ) count_missing_activities = fields.Integer( string="Missing Activities", @@ -59,6 +58,13 @@ def _onchange_member_ids(self): if self.user_id and self.user_id not in self.member_ids: self.user_id = False + @api.onchange('user_id') + def _onchange_user_id(self): + if self.user_id and self.user_id not in self.member_ids: + members_ids = self.member_ids.ids + members_ids.append(self.user_id.id) + self.member_ids = [(4, member) for member in members_ids] + def assign_team_to_unassigned_activities(self): activity_model = self.env['mail.activity'] for team in self: @@ -68,4 +74,5 @@ def assign_team_to_unassigned_activities(self): if team.res_model_ids: domain.append(('res_model_id', 'in', team.res_model_ids.ids)) missing_activities = activity_model.search(domain) - missing_activities.write({'team_id': team.id}) + for missing_activity in missing_activities: + missing_activity.write({'team_id': team.id}) diff --git a/mail_activity_team/tests/test_mail_activity_team.py b/mail_activity_team/tests/test_mail_activity_team.py index 3f7928cbc..413e4122a 100644 --- a/mail_activity_team/tests/test_mail_activity_team.py +++ b/mail_activity_team/tests/test_mail_activity_team.py @@ -100,7 +100,7 @@ def test_activity_onchanges(self): self.assertEqual(self.act2.team_id, self.team2) self.act2.team_id = self.team1 self.act2._onchange_team_id() - self.assertFalse(self.act2.user_id) + self.assertEqual(self.act2.user_id, self.team1.member_ids) with self.assertRaises(ValidationError): self.act2.write({ 'user_id': self.employee2.id, diff --git a/mail_activity_team/views/mail_activity_team_views.xml b/mail_activity_team/views/mail_activity_team_views.xml index 72b49a1d9..6ecba09a5 100644 --- a/mail_activity_team/views/mail_activity_team_views.xml +++ b/mail_activity_team/views/mail_activity_team_views.xml @@ -27,7 +27,7 @@ - + Date: Mon, 24 Dec 2018 13:19:52 +0100 Subject: [PATCH 06/81] [IMP] Add search filter for My Team Activities --- mail_activity_team/views/mail_activity_views.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mail_activity_team/views/mail_activity_views.xml b/mail_activity_team/views/mail_activity_views.xml index 93ad71b91..ec0ecd471 100644 --- a/mail_activity_team/views/mail_activity_views.xml +++ b/mail_activity_team/views/mail_activity_views.xml @@ -61,6 +61,9 @@ + + + From 7abc294e1d30296137ef56a171174373284bfccb Mon Sep 17 00:00:00 2001 From: David Beal Date: Wed, 10 Jul 2019 15:41:57 +0200 Subject: [PATCH 07/81] FIX mail_activ_team: always allow superuser --- .../i18n/mail_activity_team.pot | 139 ++++++++++++++++++ mail_activity_team/models/mail_activity.py | 11 +- .../static/description/index.html | 31 +++- 3 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 mail_activity_team/i18n/mail_activity_team.pot diff --git a/mail_activity_team/i18n/mail_activity_team.pot b/mail_activity_team/i18n/mail_activity_team.pot new file mode 100644 index 000000000..a6173eed0 --- /dev/null +++ b/mail_activity_team/i18n/mail_activity_team.pot @@ -0,0 +1,139 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_activity_team +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active +msgid "Active" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model,name:mail_activity_team.model_mail_activity +msgid "Activity" +msgstr "" + +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_team_view_form +msgid "Activity Team" +msgstr "" + +#. module: mail_activity_team +#: model:ir.actions.act_window,name:mail_activity_team.mail_activity_team_action +#: model:ir.model.fields,field_description:mail_activity_team.field_res_users__activity_team_ids +#: model:ir.ui.menu,name:mail_activity_team.menu_mail_activity_team +msgid "Activity Teams" +msgstr "" + +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_team_view_form +msgid "Assign to missing activities" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__create_uid +msgid "Created by" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__create_date +msgid "Created on" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__display_name +msgid "Display Name" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__id +msgid "ID" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team____last_update +msgid "Last Modified on" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__write_date +msgid "Last Updated on" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model,name:mail_activity_team.model_mail_activity_team +msgid "Mail Activity Team" +msgstr "" + +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_team_view_form +msgid "Members" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__count_missing_activities +msgid "Missing Activities" +msgstr "" + +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search +msgid "My Team Activities" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__name +msgid "Name" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search +msgid "Team" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__user_id +msgid "Team Leader" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__member_ids +msgid "Team Members" +msgstr "" + +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban +msgid "Team:" +msgstr "" + +#. module: mail_activity_team +#: code:addons/mail_activity_team/models/mail_activity.py:72 +#, python-format +msgid "The assigned user is not member of the team." +msgstr "" + +#. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__res_model_ids +msgid "Used models" +msgstr "" + +#. module: mail_activity_team +#: model:ir.model,name:mail_activity_team.model_res_users +msgid "Users" +msgstr "" + diff --git a/mail_activity_team/models/mail_activity.py b/mail_activity_team/models/mail_activity.py index 1fccf7463..bfb0f3516 100644 --- a/mail_activity_team/models/mail_activity.py +++ b/mail_activity_team/models/mail_activity.py @@ -1,6 +1,6 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, models, fields, _ +from odoo import api, models, fields, _, SUPERUSER_ID from odoo.exceptions import ValidationError @@ -59,7 +59,14 @@ def _onchange_team_id(self): @api.constrains('team_id', 'user_id') def _check_team_and_user(self): for activity in self: - if activity.team_id and activity.user_id and \ + # SUPERUSER is used to put mail.activity on some objects + # like sale.order coming from stock.picking + # (for example with exception type activity, with no backorder). + # SUPERUSER is inactive and then even if you add it + # to member_ids it's not taken account + # To not be blocked we must add it to constraint condition + if activity.user_id.id != SUPERUSER_ID and activity.team_id and \ + activity.user_id and \ activity.user_id not in self.team_id.member_ids: raise ValidationError( _('The assigned user is not member of the team.')) diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index 1ee2f86d0..a48c4f23d 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -3,13 +3,13 @@ - + Mail Activity Team -
-

Mail Activity Team

+
+ + +Odoo Community Association + +
+

Mail Activity Team

-

Alpha License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Alpha License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

Important

@@ -392,7 +397,7 @@

Mail Activity Team

-

Usage

+

Usage

To set up new teams:

  1. Go to Settings / Activate developer mode
  2. @@ -409,7 +414,7 @@

    Usage

    / Activities, and then filter by a specific team or group by teams.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -417,16 +422,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Sodexis
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -478,5 +483,6 @@

Maintainers

+
From fd519536fb49c0e2021fb01415497ae228ba8bdd Mon Sep 17 00:00:00 2001 From: Joel Estrada Date: Tue, 22 Jul 2025 12:37:09 +0200 Subject: [PATCH 67/81] [BUILD] mail_post_defer: mark as rebel mail_post_defer breaks tests for mail_tracking, so it's better to split it. https://github.com/OCA/social/commit/b782115eb2b8adf08ff99298dee98a1ac757bc26 @moduon MT-10471 --- mail_activity_team/patch.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/mail_activity_team/patch.py b/mail_activity_team/patch.py index ace580836..e6ae6cfda 100644 --- a/mail_activity_team/patch.py +++ b/mail_activity_team/patch.py @@ -6,7 +6,8 @@ @api.model_create_multi def mail_activity__create(self, vals_list): # Monkeypatch for mail's mail.activity's create method to prevent - # UnboundLocalError: cannot access local variable 'activity' where it is not associated with a value + # UnboundLocalError: cannot access local variable 'activity' + # where it is not associated with a value # which occurs when this module creates activities without a user_id. # Patch below is according to https://github.com/odoo/odoo/pull/197864 activities = super(MailActivity, self).create(vals_list) @@ -14,17 +15,21 @@ def mail_activity__create(self, vals_list): # find partners related to responsible users, separate readable from unreadable if any(user != self.env.user for user in activities.user_id): user_partners = activities.user_id.partner_id - readable_user_partners = user_partners._filtered_access('read') + readable_user_partners = user_partners._filtered_access("read") else: readable_user_partners = self.env.user.partner_id # when creating activities for other: send a notification to assigned user; - if self.env.context.get('mail_activity_quick_update'): - activities_to_notify = self.env['mail.activity'] + if self.env.context.get("mail_activity_quick_update"): + activities_to_notify = self.env["mail.activity"] else: - activities_to_notify = activities.filtered(lambda act: act.user_id != self.env.user) + activities_to_notify = activities.filtered( + lambda act: act.user_id != self.env.user + ) if activities_to_notify: - to_sudo = activities_to_notify.filtered(lambda act: act.user_id.partner_id not in readable_user_partners) + to_sudo = activities_to_notify.filtered( + lambda act: act.user_id.partner_id not in readable_user_partners + ) other = activities_to_notify - to_sudo to_sudo.sudo().action_notify() other.action_notify() @@ -32,20 +37,29 @@ def mail_activity__create(self, vals_list): # subscribe (batch by model and user to speedup) for model, activity_data in activities._classify_by_model().items(): per_user = dict() - for activity in activity_data['activities'].filtered(lambda act: act.user_id): + for activity in activity_data["activities"].filtered(lambda act: act.user_id): if activity.user_id not in per_user: per_user[activity.user_id] = [activity.res_id] else: per_user[activity.user_id].append(activity.res_id) for user, res_ids in per_user.items(): - pids = user.partner_id.ids if user.partner_id in readable_user_partners else user.sudo().partner_id.ids + pids = ( + user.partner_id.ids + if user.partner_id in readable_user_partners + else user.sudo().partner_id.ids + ) self.env[model].browse(res_ids).message_subscribe(partner_ids=pids) # send notifications about activity creation - todo_activities = activities.filtered(lambda act: act.date_deadline <= fields.Date.today()) + todo_activities = activities.filtered( + lambda act: act.date_deadline <= fields.Date.today() + ) if todo_activities: # Monkeypatch start - # activity.user_id._bus_send("mail.activity/updated", {"activity_created": True}) - todo_activities.user_id._bus_send("mail.activity/updated", {"activity_created": True}) + # activity.user_id._bus_send("mail.activity/updated", + # {"activity_created": True}) + todo_activities.user_id._bus_send( + "mail.activity/updated", {"activity_created": True} + ) # Monkeypatch end return activities From 2ac8959e9ffba0d6a81fd7d043f13af318a0da46 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 6 Oct 2025 11:40:03 +0000 Subject: [PATCH 68/81] [UPD] Update mail_activity_team.pot --- mail_activity_team/i18n/mail_activity_team.pot | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mail_activity_team/i18n/mail_activity_team.pot b/mail_activity_team/i18n/mail_activity_team.pot index b0bb7eaac..5cf1bb441 100644 --- a/mail_activity_team/i18n/mail_activity_team.pot +++ b/mail_activity_team/i18n/mail_activity_team.pot @@ -198,9 +198,18 @@ msgid "User" msgstr "" #. module: mail_activity_team +#: model:ir.model.fields,field_description:mail_activity_team.field_account_bank_statement_line__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_account_journal__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_account_move__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_account_payment__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_account_setup_bank_manual_config__activity_team_user_ids #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_mixin__activity_team_user_ids #: model:ir.model.fields,field_description:mail_activity_team.field_mailing_mailing__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_product_pricelist__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_product_product__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_product_template__activity_team_user_ids #: model:ir.model.fields,field_description:mail_activity_team.field_res_partner__activity_team_user_ids +#: model:ir.model.fields,field_description:mail_activity_team.field_res_partner_bank__activity_team_user_ids #: model:ir.model.fields,field_description:mail_activity_team.field_res_users__activity_team_user_ids msgid "test field" msgstr "" From a2957e9404c7c151892b3a80742dc02de8420ed8 Mon Sep 17 00:00:00 2001 From: Weblate Date: Mon, 6 Oct 2025 11:44:08 +0000 Subject: [PATCH 69/81] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: mail-18.0/mail-18.0-mail_activity_team Translate-URL: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_activity_team/ --- mail_activity_team/i18n/es.po | 11 ++++++++--- mail_activity_team/i18n/fr.po | 11 ++++++++--- mail_activity_team/i18n/it.po | 11 ++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/mail_activity_team/i18n/es.po b/mail_activity_team/i18n/es.po index e4c13f050..dd1828a10 100644 --- a/mail_activity_team/i18n/es.po +++ b/mail_activity_team/i18n/es.po @@ -16,6 +16,12 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.17\n" +#. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 +msgid "(Team" +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -118,7 +124,6 @@ msgstr "Actividades Pendientes" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "My Activities" msgstr "Mis Actividades" @@ -138,6 +143,8 @@ msgid "Server Action" msgstr "Acción de Servidor" #. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id #: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" @@ -146,7 +153,6 @@ msgstr "Equipo" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "Team Activities" msgstr "Actividades de Equipo" @@ -179,7 +185,6 @@ msgstr "Equipo:" #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 -#, python-format msgid "" "The assigned user %(user_name)s is not member of the team %(team_name)s." msgstr "" diff --git a/mail_activity_team/i18n/fr.po b/mail_activity_team/i18n/fr.po index ad70cf2d0..9d0bcc27e 100644 --- a/mail_activity_team/i18n/fr.po +++ b/mail_activity_team/i18n/fr.po @@ -16,6 +16,12 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.3.2\n" +#. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 +msgid "(Team" +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -118,7 +124,6 @@ msgstr "" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "My Activities" msgstr "" @@ -138,6 +143,8 @@ msgid "Server Action" msgstr "" #. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id #: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" @@ -146,7 +153,6 @@ msgstr "" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "Team Activities" msgstr "" @@ -179,7 +185,6 @@ msgstr "" #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 -#, python-format msgid "" "The assigned user %(user_name)s is not member of the team %(team_name)s." msgstr "" diff --git a/mail_activity_team/i18n/it.po b/mail_activity_team/i18n/it.po index 3ed4b2947..f035d2fc7 100644 --- a/mail_activity_team/i18n/it.po +++ b/mail_activity_team/i18n/it.po @@ -16,6 +16,12 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 5.6.2\n" +#. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 +msgid "(Team" +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -118,7 +124,6 @@ msgstr "Attività Mancanti" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "My Activities" msgstr "Le mie attività" @@ -138,6 +143,8 @@ msgid "Server Action" msgstr "Azione server" #. module: mail_activity_team +#. odoo-javascript +#: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id #: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" @@ -146,7 +153,6 @@ msgstr "Team" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/components/activity_menu_view/activity_menu_view.xml:0 -#, python-format msgid "Team Activities" msgstr "Attività team" @@ -179,7 +185,6 @@ msgstr "Team:" #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 -#, python-format msgid "" "The assigned user %(user_name)s is not member of the team %(team_name)s." msgstr "" From 78b3d44754df10bd64179d5f0f5aa1d6fd2af8b2 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 7 Oct 2025 08:16:40 +0000 Subject: [PATCH 70/81] Translated using Weblate (Italian) Currently translated at 100.0% (35 of 35 strings) Translation: mail-18.0/mail-18.0-mail_activity_team Translate-URL: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_activity_team/it/ --- mail_activity_team/i18n/it.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mail_activity_team/i18n/it.po b/mail_activity_team/i18n/it.po index f035d2fc7..5c9ff877c 100644 --- a/mail_activity_team/i18n/it.po +++ b/mail_activity_team/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-01-19 14:06+0000\n" +"PO-Revision-Date: 2025-10-07 08:20+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -14,13 +14,13 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.6.2\n" +"X-Generator: Weblate 5.10.4\n" #. module: mail_activity_team #. odoo-javascript #: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 msgid "(Team" -msgstr "" +msgstr "(Squadra" #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active From d8834e99f31c142e9d53ad111b4d6135ed2e2953 Mon Sep 17 00:00:00 2001 From: Marie Lejeune Date: Wed, 15 Oct 2025 10:54:49 +0200 Subject: [PATCH 71/81] [IMP] Mail Activity Team: switch to Beta version --- mail_activity_team/README.rst | 15 ++------ mail_activity_team/__manifest__.py | 2 +- .../static/description/index.html | 34 ++++++------------- 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 5b5b4d01f..7122a3ebd 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ================== Mail Activity Team ================== @@ -14,10 +10,10 @@ Mail Activity Team !! source digest: sha256:2f89995e87d2922a9f795b1c56269d35e8145119ef8a3b116f8cd62b78b3d178 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status - :alt: Alpha -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :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%2Fmail-lightgray.png?logo=github @@ -34,11 +30,6 @@ Mail Activity Team This module adds the possibility to assign teams to activities. -.. IMPORTANT:: - This is an alpha version, the data model and design can change at any time without warning. - Only for development or testing purpose, do not use in production. - `More details on development status `_ - **Table of contents** .. contents:: diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index b1f445dcb..f87b2e682 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -6,7 +6,7 @@ "name": "Mail Activity Team", "summary": "Add Teams to Activities", "version": "18.0.1.0.0", - "development_status": "Alpha", + "development_status": "Beta", "category": "Social Network", "website": "https://github.com/OCA/mail", "author": "ForgeFlow, Sodexis, Odoo Community Association (OCA)", diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index a837f3714..ccfecda6b 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Mail Activity Team -
+
+

Mail Activity Team

- - -Odoo Community Association - -
-

Mail Activity Team

-

Alpha License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

-
-

Important

-

This is an alpha version, the data model and design can change at any time without warning. -Only for development or testing purpose, do not use in production. -More details on development status

-

Table of contents

    @@ -397,7 +386,7 @@

    Mail Activity Team

-

Usage

+

Usage

To set up new teams:

  1. Go to Settings / Activate developer mode
  2. @@ -414,7 +403,7 @@

    Usage

    / Activities, and then filter by a specific team or group by teams.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -422,16 +411,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Sodexis
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -483,6 +472,5 @@

Maintainers

-
From d96ddd5d6a205226dfdc99b127216a4a63deccad Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 27 Oct 2025 11:35:27 +0000 Subject: [PATCH 72/81] [BOT] post-merge updates --- mail_activity_team/README.rst | 8 +++-- mail_activity_team/__manifest__.py | 2 +- .../static/description/index.html | 30 +++++++++++-------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 7122a3ebd..752d566a1 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ================== Mail Activity Team ================== @@ -7,13 +11,13 @@ Mail Activity Team !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:2f89995e87d2922a9f795b1c56269d35e8145119ef8a3b116f8cd62b78b3d178 + !! source digest: sha256:51672fdadfaeec24c2ecce86ab4698c99dfcc197c6f803ab4281af9248dd1c0d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |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 +.. |badge2| image:: https://img.shields.io/badge/license-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%2Fmail-lightgray.png?logo=github diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index f87b2e682..fa7d444fd 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Mail Activity Team", "summary": "Add Teams to Activities", - "version": "18.0.1.0.0", + "version": "18.0.1.0.1", "development_status": "Beta", "category": "Social Network", "website": "https://github.com/OCA/mail", diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index ccfecda6b..07fbbce1d 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -3,7 +3,7 @@ -Mail Activity Team +README.rst -
-

Mail Activity Team

+
+ + +Odoo Community Association + +
+

Mail Activity Team

-

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

Table of contents

@@ -386,7 +391,7 @@

Mail Activity Team

-

Usage

+

Usage

To set up new teams:

  1. Go to Settings / Activate developer mode
  2. @@ -403,7 +408,7 @@

    Usage

    / Activities, and then filter by a specific team or group by teams.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -411,16 +416,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Sodexis
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -472,5 +477,6 @@

Maintainers

+
From 23871552bdc671384283a5495e2f14efc530b5ab Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Mon, 27 Oct 2025 12:22:24 +0100 Subject: [PATCH 73/81] [REV] mail_activity_team: revert obsolete monkey patch Issue fixed in https://github.com/odoo/odoo/pull/215880 --- mail_activity_team/__init__.py | 1 - mail_activity_team/__manifest__.py | 1 - mail_activity_team/hooks.py | 13 ------ mail_activity_team/patch.py | 65 ------------------------------ 4 files changed, 80 deletions(-) delete mode 100644 mail_activity_team/hooks.py delete mode 100644 mail_activity_team/patch.py diff --git a/mail_activity_team/__init__.py b/mail_activity_team/__init__.py index c19ab79ba..9b4296142 100644 --- a/mail_activity_team/__init__.py +++ b/mail_activity_team/__init__.py @@ -1,3 +1,2 @@ -from .hooks import post_load_hook from . import models from . import wizard diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index fa7d444fd..09a562f76 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -30,5 +30,4 @@ "mail_activity_team/static/src/models/*", ], }, - "post_load": "post_load_hook", } diff --git a/mail_activity_team/hooks.py b/mail_activity_team/hooks.py deleted file mode 100644 index 4611d85f0..000000000 --- a/mail_activity_team/hooks.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging - -from odoo.addons.mail.models.mail_activity import MailActivity - -from .patch import mail_activity__create - -_logger = logging.getLogger(__name__) - - -def post_load_hook(): - """See patch.py for more info""" - MailActivity.create = mail_activity__create - _logger.info("PATCHED mail's mail.activity create") diff --git a/mail_activity_team/patch.py b/mail_activity_team/patch.py deleted file mode 100644 index e6ae6cfda..000000000 --- a/mail_activity_team/patch.py +++ /dev/null @@ -1,65 +0,0 @@ -from odoo import api, fields - -from odoo.addons.mail.models.mail_activity import MailActivity - - -@api.model_create_multi -def mail_activity__create(self, vals_list): - # Monkeypatch for mail's mail.activity's create method to prevent - # UnboundLocalError: cannot access local variable 'activity' - # where it is not associated with a value - # which occurs when this module creates activities without a user_id. - # Patch below is according to https://github.com/odoo/odoo/pull/197864 - activities = super(MailActivity, self).create(vals_list) - - # find partners related to responsible users, separate readable from unreadable - if any(user != self.env.user for user in activities.user_id): - user_partners = activities.user_id.partner_id - readable_user_partners = user_partners._filtered_access("read") - else: - readable_user_partners = self.env.user.partner_id - - # when creating activities for other: send a notification to assigned user; - if self.env.context.get("mail_activity_quick_update"): - activities_to_notify = self.env["mail.activity"] - else: - activities_to_notify = activities.filtered( - lambda act: act.user_id != self.env.user - ) - if activities_to_notify: - to_sudo = activities_to_notify.filtered( - lambda act: act.user_id.partner_id not in readable_user_partners - ) - other = activities_to_notify - to_sudo - to_sudo.sudo().action_notify() - other.action_notify() - - # subscribe (batch by model and user to speedup) - for model, activity_data in activities._classify_by_model().items(): - per_user = dict() - for activity in activity_data["activities"].filtered(lambda act: act.user_id): - if activity.user_id not in per_user: - per_user[activity.user_id] = [activity.res_id] - else: - per_user[activity.user_id].append(activity.res_id) - for user, res_ids in per_user.items(): - pids = ( - user.partner_id.ids - if user.partner_id in readable_user_partners - else user.sudo().partner_id.ids - ) - self.env[model].browse(res_ids).message_subscribe(partner_ids=pids) - - # send notifications about activity creation - todo_activities = activities.filtered( - lambda act: act.date_deadline <= fields.Date.today() - ) - if todo_activities: - # Monkeypatch start - # activity.user_id._bus_send("mail.activity/updated", - # {"activity_created": True}) - todo_activities.user_id._bus_send( - "mail.activity/updated", {"activity_created": True} - ) - # Monkeypatch end - return activities From 63c3a58573204cbe68dde232ca4f85eadd49d1ec Mon Sep 17 00:00:00 2001 From: Christopher Rogos Date: Thu, 11 Dec 2025 08:47:41 +0000 Subject: [PATCH 74/81] [IMP] mail_activity_team: remove mail_activity_board dependency --- mail_activity_team/README.rst | 40 +++++++------- mail_activity_team/__manifest__.py | 4 +- .../static/description/index.html | 28 ++++------ .../views/mail_activity_views.xml | 53 +++++-------------- 4 files changed, 43 insertions(+), 82 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 752d566a1..ed64ca2ef 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ================== Mail Activity Team ================== @@ -17,7 +13,7 @@ Mail Activity Team .. |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/license-AGPL--3-blue.png +.. |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%2Fmail-lightgray.png?logo=github @@ -81,35 +77,35 @@ Authors Contributors ------------ -- `ForgeFlow `__: +- `ForgeFlow `__: - - Jordi Ballester Alomar (jordi.ballester@forgeflow.com) - - Miquel Raïch (miquel.raich@forgeflow.com) - - Bernat Puig Font (bernat.puig@forgeflow.com) + - Jordi Ballester Alomar (jordi.ballester@forgeflow.com) + - Miquel Raïch (miquel.raich@forgeflow.com) + - Bernat Puig Font (bernat.puig@forgeflow.com) -- Pedro Gonzalez (pedro.gonzalez@pesol.es) -- `Tecnativa `__: +- Pedro Gonzalez (pedro.gonzalez@pesol.es) +- `Tecnativa `__: - - David Vidal + - David Vidal -- `Dynapps `__: +- `Dynapps `__: - - Raf Ven + - Raf Ven -- [Trobz] (https://trobz.com): +- [Trobz] (https://trobz.com): - - Son Ho sonhd@trobz.com + - Son Ho sonhd@trobz.com -- [Camptocamp] (https://camptocamp.com): +- [Camptocamp] (https://camptocamp.com): - - Vincent Van Rossem vincent.vanrossem@camptocamp.com - - Italo Lopes italo.lopes@camptocamp.com + - Vincent Van Rossem vincent.vanrossem@camptocamp.com + - Italo Lopes italo.lopes@camptocamp.com -- `CorporateHub `__ +- `CorporateHub `__ - - Alexey Pelykh alexey.pelykh@corphub.eu + - Alexey Pelykh alexey.pelykh@corphub.eu -- Stefan Rijnhart (stefan@opener.amsterdam) +- Stefan Rijnhart (stefan@opener.amsterdam) Other credits ------------- diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index 09a562f76..9c4ca9bb7 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -5,14 +5,14 @@ { "name": "Mail Activity Team", "summary": "Add Teams to Activities", - "version": "18.0.1.0.1", + "version": "18.0.1.0.2", "development_status": "Beta", "category": "Social Network", "website": "https://github.com/OCA/mail", "author": "ForgeFlow, Sodexis, Odoo Community Association (OCA)", "license": "AGPL-3", "installable": True, - "depends": ["mail_activity_board", "web"], + "depends": ["mail", "web"], "data": [ "security/ir.model.access.csv", "security/mail_activity_team_security.xml", diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index 07fbbce1d..13c2f6204 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Mail Activity Team -
+
+

Mail Activity Team

- - -Odoo Community Association - -
-

Mail Activity Team

-

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

Table of contents

@@ -391,7 +386,7 @@

Mail Activity Team

-

Usage

+

Usage

To set up new teams:

  1. Go to Settings / Activate developer mode
  2. @@ -408,7 +403,7 @@

    Usage

    / Activities, and then filter by a specific team or group by teams.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -416,16 +411,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Sodexis
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -477,6 +472,5 @@

Maintainers

-
diff --git a/mail_activity_team/views/mail_activity_views.xml b/mail_activity_team/views/mail_activity_views.xml index a1ec3bc16..07fb47f3a 100644 --- a/mail_activity_team/views/mail_activity_views.xml +++ b/mail_activity_team/views/mail_activity_views.xml @@ -22,7 +22,6 @@ - mail.activity.view.tree mail.activity @@ -34,44 +33,16 @@ - - mail.activity.view.form - mail.activity - - - - not team_id - - - - - - - - - + mail.activity.boards.view.kanban mail.activity - + - - - - -
+
- Team: -
+ Team: + +
@@ -80,22 +51,22 @@ mail.activity.boards.view.search mail.activity - + - + - + - - - + + + From 344c7b142f4e290f08b86fa8827e6b1018ba97e8 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 11 Dec 2025 10:37:58 +0000 Subject: [PATCH 75/81] [UPD] Update mail_activity_team.pot --- mail_activity_team/i18n/mail_activity_team.pot | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mail_activity_team/i18n/mail_activity_team.pot b/mail_activity_team/i18n/mail_activity_team.pot index 5cf1bb441..40bf6c7b3 100644 --- a/mail_activity_team/i18n/mail_activity_team.pot +++ b/mail_activity_team/i18n/mail_activity_team.pot @@ -19,6 +19,11 @@ msgstr "" msgid "(Team" msgstr "" +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban_open_target +msgid "Team: " +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -143,7 +148,6 @@ msgstr "" #. odoo-javascript #: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" msgstr "" @@ -174,11 +178,6 @@ msgstr "" msgid "Team user" msgstr "" -#. module: mail_activity_team -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban -msgid "Team:" -msgstr "" - #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 From 590e4de72d73ef40559fd279eee8a6f591e76d25 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 11 Dec 2025 10:42:00 +0000 Subject: [PATCH 76/81] [BOT] post-merge updates --- mail_activity_team/README.rst | 42 ++++++++++--------- .../static/description/index.html | 30 +++++++------ 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index ed64ca2ef..96a8adda7 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ================== Mail Activity Team ================== @@ -7,13 +11,13 @@ Mail Activity Team !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:51672fdadfaeec24c2ecce86ab4698c99dfcc197c6f803ab4281af9248dd1c0d + !! source digest: sha256:4ddbbf29e9941ec7189251a2a0c0219aa7dbf652e67e7684b632cebbeb498393 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |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 +.. |badge2| image:: https://img.shields.io/badge/license-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%2Fmail-lightgray.png?logo=github @@ -77,35 +81,35 @@ Authors Contributors ------------ -- `ForgeFlow `__: +- `ForgeFlow `__: - - Jordi Ballester Alomar (jordi.ballester@forgeflow.com) - - Miquel Raïch (miquel.raich@forgeflow.com) - - Bernat Puig Font (bernat.puig@forgeflow.com) + - Jordi Ballester Alomar (jordi.ballester@forgeflow.com) + - Miquel Raïch (miquel.raich@forgeflow.com) + - Bernat Puig Font (bernat.puig@forgeflow.com) -- Pedro Gonzalez (pedro.gonzalez@pesol.es) -- `Tecnativa `__: +- Pedro Gonzalez (pedro.gonzalez@pesol.es) +- `Tecnativa `__: - - David Vidal + - David Vidal -- `Dynapps `__: +- `Dynapps `__: - - Raf Ven + - Raf Ven -- [Trobz] (https://trobz.com): +- [Trobz] (https://trobz.com): - - Son Ho sonhd@trobz.com + - Son Ho sonhd@trobz.com -- [Camptocamp] (https://camptocamp.com): +- [Camptocamp] (https://camptocamp.com): - - Vincent Van Rossem vincent.vanrossem@camptocamp.com - - Italo Lopes italo.lopes@camptocamp.com + - Vincent Van Rossem vincent.vanrossem@camptocamp.com + - Italo Lopes italo.lopes@camptocamp.com -- `CorporateHub `__ +- `CorporateHub `__ - - Alexey Pelykh alexey.pelykh@corphub.eu + - Alexey Pelykh alexey.pelykh@corphub.eu -- Stefan Rijnhart (stefan@opener.amsterdam) +- Stefan Rijnhart (stefan@opener.amsterdam) Other credits ------------- diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index 13c2f6204..a35f00d28 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -3,7 +3,7 @@ -Mail Activity Team +README.rst -
-

Mail Activity Team

+
+ + +Odoo Community Association + +
+

Mail Activity Team

-

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

Table of contents

@@ -386,7 +391,7 @@

Mail Activity Team

-

Usage

+

Usage

To set up new teams:

  1. Go to Settings / Activate developer mode
  2. @@ -403,7 +408,7 @@

    Usage

    / Activities, and then filter by a specific team or group by teams.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -411,16 +416,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Sodexis
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -472,5 +477,6 @@

Maintainers

+
From 57799f0275be1c9682f680b41843edf2a7a04cdb Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 11 Dec 2025 10:42:13 +0000 Subject: [PATCH 77/81] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: mail-18.0/mail-18.0-mail_activity_team Translate-URL: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_activity_team/ --- mail_activity_team/i18n/es.po | 14 ++++++++------ mail_activity_team/i18n/fr.po | 11 +++++------ mail_activity_team/i18n/it.po | 14 ++++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/mail_activity_team/i18n/es.po b/mail_activity_team/i18n/es.po index dd1828a10..6e3f88f37 100644 --- a/mail_activity_team/i18n/es.po +++ b/mail_activity_team/i18n/es.po @@ -22,6 +22,11 @@ msgstr "" msgid "(Team" msgstr "" +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban_open_target +msgid "Team: " +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -146,7 +151,6 @@ msgstr "Acción de Servidor" #. odoo-javascript #: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" msgstr "Equipo" @@ -177,11 +181,6 @@ msgstr "" msgid "Team user" msgstr "Usuario del Equipo" -#. module: mail_activity_team -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban -msgid "Team:" -msgstr "Equipo:" - #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 @@ -218,5 +217,8 @@ msgstr "Usuario" msgid "test field" msgstr "campo de prueba" +#~ msgid "Team:" +#~ msgstr "Equipo:" + #~ msgid "Last Modified on" #~ msgstr "Última Modificación el" diff --git a/mail_activity_team/i18n/fr.po b/mail_activity_team/i18n/fr.po index 9d0bcc27e..45a963f64 100644 --- a/mail_activity_team/i18n/fr.po +++ b/mail_activity_team/i18n/fr.po @@ -22,6 +22,11 @@ msgstr "" msgid "(Team" msgstr "" +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban_open_target +msgid "Team: " +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -146,7 +151,6 @@ msgstr "" #. odoo-javascript #: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" msgstr "" @@ -177,11 +181,6 @@ msgstr "" msgid "Team user" msgstr "" -#. module: mail_activity_team -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban -msgid "Team:" -msgstr "" - #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 diff --git a/mail_activity_team/i18n/it.po b/mail_activity_team/i18n/it.po index 5c9ff877c..f7bf010e3 100644 --- a/mail_activity_team/i18n/it.po +++ b/mail_activity_team/i18n/it.po @@ -22,6 +22,11 @@ msgstr "" msgid "(Team" msgstr "(Squadra" +#. module: mail_activity_team +#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban_open_target +msgid "Team: " +msgstr "" + #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active msgid "Active" @@ -146,7 +151,6 @@ msgstr "Azione server" #. odoo-javascript #: code:addons/mail_activity_team/static/src/core/web/activity.xml:0 #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity__team_id -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_search msgid "Team" msgstr "Team" @@ -177,11 +181,6 @@ msgstr "Team assegnato a" msgid "Team user" msgstr "Utente del team" -#. module: mail_activity_team -#: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban -msgid "Team:" -msgstr "Team:" - #. module: mail_activity_team #. odoo-python #: code:addons/mail_activity_team/models/mail_activity.py:0 @@ -218,6 +217,9 @@ msgstr "Utente" msgid "test field" msgstr "campo test" +#~ msgid "Team:" +#~ msgstr "Team:" + #~ msgid "Last Modified on" #~ msgstr "Ultima modifica il" From 87709e01489de055be957deff580f8cc644eff89 Mon Sep 17 00:00:00 2001 From: mymage Date: Sun, 14 Dec 2025 19:15:55 +0000 Subject: [PATCH 78/81] Translated using Weblate (Italian) Currently translated at 100.0% (35 of 35 strings) Translation: mail-18.0/mail-18.0-mail_activity_team Translate-URL: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_activity_team/it/ --- mail_activity_team/i18n/it.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mail_activity_team/i18n/it.po b/mail_activity_team/i18n/it.po index f7bf010e3..31f62cd26 100644 --- a/mail_activity_team/i18n/it.po +++ b/mail_activity_team/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-10-07 08:20+0000\n" +"PO-Revision-Date: 2025-12-14 21:42+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -25,7 +25,7 @@ msgstr "(Squadra" #. module: mail_activity_team #: model_terms:ir.ui.view,arch_db:mail_activity_team.mail_activity_view_kanban_open_target msgid "Team: " -msgstr "" +msgstr "Team: " #. module: mail_activity_team #: model:ir.model.fields,field_description:mail_activity_team.field_mail_activity_team__active From 99b4647291060f37d0f4d121721d9bc4d72d9a77 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 11 Feb 2026 17:09:10 +0000 Subject: [PATCH 79/81] [BOT] post-merge updates --- mail_activity_team/README.rst | 2 +- mail_activity_team/__manifest__.py | 2 +- mail_activity_team/static/description/index.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 96a8adda7..25f65e0a5 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -11,7 +11,7 @@ Mail Activity Team !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:4ddbbf29e9941ec7189251a2a0c0219aa7dbf652e67e7684b632cebbeb498393 + !! source digest: sha256:ca0203ad2f0fed4e4686b319424332ac44446e2380683a802c1052f78584cfa4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index 9c4ca9bb7..f03997720 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Mail Activity Team", "summary": "Add Teams to Activities", - "version": "18.0.1.0.2", + "version": "18.0.1.0.3", "development_status": "Beta", "category": "Social Network", "website": "https://github.com/OCA/mail", diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index a35f00d28..f00a68aeb 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -372,7 +372,7 @@

Mail Activity Team

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:4ddbbf29e9941ec7189251a2a0c0219aa7dbf652e67e7684b632cebbeb498393 +!! source digest: sha256:ca0203ad2f0fed4e4686b319424332ac44446e2380683a802c1052f78584cfa4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

From a7e43b36e1c5fd6680378f49bcff9306fda642ce Mon Sep 17 00:00:00 2001 From: Muaaz Siddiq Date: Mon, 23 Feb 2026 08:38:51 +0100 Subject: [PATCH 80/81] [MIG] mail_activity_team: Migration to 19.0 --- mail_activity_team/README.rst | 16 +- mail_activity_team/__manifest__.py | 4 +- .../migrations/18.0.1.0.0/post-migration.py | 9 - mail_activity_team/models/__init__.py | 5 +- mail_activity_team/models/mail_activity.py | 72 +++-- .../models/mail_activity_mixin.py | 20 +- .../models/mail_activity_plan_template.py | 95 ++++++ .../models/mail_activity_team.py | 4 +- mail_activity_team/readme/CREDITS.md | 1 - mail_activity_team/readme/USAGE.md | 3 + .../security/mail_activity_team_security.xml | 2 +- .../static/description/index.html | 10 +- .../static/src/core/web/activity.xml | 23 +- .../static/src/models/activity_menu.esm.js | 8 +- mail_activity_team/tests/__init__.py | 1 + .../tests/test_mail_activity.py | 295 ++++++++++++++++++ .../tests/test_mail_activity_team.py | 273 ++++++++++++++-- .../mail_activity_plan_template_views.xml | 24 ++ .../views/mail_activity_plan_views.xml | 15 + .../views/mail_activity_views.xml | 2 +- .../wizard/mail_activity_schedule.py | 94 +++++- 21 files changed, 840 insertions(+), 136 deletions(-) delete mode 100644 mail_activity_team/migrations/18.0.1.0.0/post-migration.py create mode 100644 mail_activity_team/models/mail_activity_plan_template.py create mode 100644 mail_activity_team/tests/test_mail_activity.py create mode 100644 mail_activity_team/views/mail_activity_plan_template_views.xml create mode 100644 mail_activity_team/views/mail_activity_plan_views.xml diff --git a/mail_activity_team/README.rst b/mail_activity_team/README.rst index 25f65e0a5..6f0ea6fcf 100644 --- a/mail_activity_team/README.rst +++ b/mail_activity_team/README.rst @@ -21,13 +21,13 @@ Mail Activity Team :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmail-lightgray.png?logo=github - :target: https://github.com/OCA/mail/tree/18.0/mail_activity_team + :target: https://github.com/OCA/mail/tree/19.0/mail_activity_team :alt: OCA/mail .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_activity_team + :target: https://translation.odoo-community.org/projects/mail-19-0/mail-19-0-mail_activity_team :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/mail&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/mail&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -56,6 +56,9 @@ Teams. When you create a new activity the application will propose the user's assigned team. +When creating activity plans, instead of assigning an activity to a +user, there is also the option to assign it to a team instead. + You can report on the activities assigned to a team going to *Dashboards / Activities*, and then filter by a specific team or group by teams. @@ -65,7 +68,7 @@ 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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -114,8 +117,7 @@ Contributors Other credits ------------- -The migration of this module from 16.0 to 17.0 was financially supported -by Camptocamp + Maintainers ----------- @@ -130,6 +132,6 @@ 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/mail `_ project on GitHub. +This module is part of the `OCA/mail `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_activity_team/__manifest__.py b/mail_activity_team/__manifest__.py index f03997720..9b10e5835 100644 --- a/mail_activity_team/__manifest__.py +++ b/mail_activity_team/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Mail Activity Team", "summary": "Add Teams to Activities", - "version": "18.0.1.0.3", + "version": "19.0.1.0.0", "development_status": "Beta", "category": "Social Network", "website": "https://github.com/OCA/mail", @@ -18,6 +18,8 @@ "security/mail_activity_team_security.xml", "wizard/mail_activity_schedule.xml", "views/ir_actions_server_views.xml", + "views/mail_activity_plan_template_views.xml", + "views/mail_activity_plan_views.xml", "views/mail_activity_type.xml", "views/mail_activity_team_views.xml", "views/mail_activity_views.xml", diff --git a/mail_activity_team/migrations/18.0.1.0.0/post-migration.py b/mail_activity_team/migrations/18.0.1.0.0/post-migration.py deleted file mode 100644 index f75fc0224..000000000 --- a/mail_activity_team/migrations/18.0.1.0.0/post-migration.py +++ /dev/null @@ -1,9 +0,0 @@ -from odoo import SUPERUSER_ID, api - - -def migrate(cr, version): - """Update noupdate ir.rule data record""" - env = api.Environment(cr, SUPERUSER_ID, {}) - rule = env.ref("mail_activity_team.mail_activity_rule_my_team") - rule.domain_force = "[('team_id', 'in', user.activity_team_ids.ids)]" - rule.perm_create = False diff --git a/mail_activity_team/models/__init__.py b/mail_activity_team/models/__init__.py index 32109baf1..ccd0cec35 100644 --- a/mail_activity_team/models/__init__.py +++ b/mail_activity_team/models/__init__.py @@ -1,6 +1,7 @@ from . import ir_actions_server -from . import mail_activity_team +from . import mail_activity_team # Has to load early from . import mail_activity from . import mail_activity_mixin -from . import res_users +from . import mail_activity_plan_template from . import mail_activity_type +from . import res_users diff --git a/mail_activity_team/models/mail_activity.py b/mail_activity_team/models/mail_activity.py index f70019e01..e2352799e 100644 --- a/mail_activity_team/models/mail_activity.py +++ b/mail_activity_team/models/mail_activity.py @@ -1,24 +1,38 @@ # Copyright 2018-22 ForgeFlow S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import SUPERUSER_ID, _, api, fields, models +from odoo import api, fields, models from odoo.exceptions import ValidationError class MailActivity(models.Model): _inherit = "mail.activity" - def _get_default_team_id(self, user_id=None): + def _get_default_team_id(self, user_id=None, model_id=None): if not user_id: - user_id = self.env.uid - res_model = self.env.context.get("default_res_model") - model = self.sudo().env["ir.model"].search([("model", "=", res_model)], limit=1) - domain = [("member_ids", "in", [user_id])] - if res_model: - domain.extend( - ["|", ("res_model_ids", "=", False), ("res_model_ids", "in", model.ids)] + user_id = self.user_id.id or self.env.user.id + if not model_id: + model_id = self.res_model_id.id if self.res_model_id else None + domain = [] + domain.append(("member_ids", "=", user_id)) + if model_id: + domain += [ + "|", + ("res_model_ids", "=", False), + ("res_model_ids", "=", model_id), + ] + if not domain: + return self.env["mail.activity.team"] + teams = self.env["mail.activity.team"].search(domain) + if model_id: + # Prefer teams with a matching model + teams = ( + teams.filtered( + lambda mat, model_id=model_id: model_id in mat.res_model_ids.ids + ) + or teams ) - return self.env["mail.activity.team"].search(domain, limit=1) + return teams[:1] user_id = fields.Many2one(string="User", required=False, default=False) team_user_id = fields.Many2one( @@ -27,10 +41,30 @@ def _get_default_team_id(self, user_id=None): team_id = fields.Many2one( comodel_name="mail.activity.team", - default=lambda s: s._get_default_team_id(), index=True, + compute="_compute_team_id", + store=True, + readonly=False, ) + @api.depends("res_model_id", "user_id") + def _compute_team_id(self): + """Assign team if no team yet or team is incompatible""" + for activity in self: + if ( + not activity.team_id + or activity.user_id + and activity.user_id not in activity.team_id.member_ids + or ( + activity.res_model_id + and activity.team_id.res_model_ids + and activity.res_model_id not in activity.team_id.res_model_ids + ) + ): + activity.team_id = activity._get_default_team_id( + activity.user_id.id, activity.res_model_id.id + ) + @api.model_create_multi def create(self, vals_list): # Differently from the previous odoo version, @@ -45,20 +79,10 @@ def create(self, vals_list): if vals.get("team_id"): # using team, we have user_id = team_user_id, # so if we don't have a user_team_id we don't want user_id too - if "user_id" in vals and not vals.get("team_user_id", False): + if "user_id" in vals and not vals.get("team_user_id"): del vals["user_id"] return super().create(vals_list) - @api.onchange("user_id") - def _onchange_user_id(self): - if not self.user_id or ( - self.team_id and self.user_id in self.team_id.member_ids - ): - return - self.team_id = self.with_context( - default_res_model=self.sudo().res_model_id.model - )._get_default_team_id(user_id=self.user_id.id) - @api.onchange("team_id") def _onchange_team_id(self): if self.team_id and self.user_id not in self.team_id.member_ids: @@ -81,14 +105,14 @@ def _check_team_and_user(self): # We must consider also users that could be archived but come from # an automatic scheduled activity if ( - activity.user_id.id != SUPERUSER_ID + activity.user_id.id != api.SUPERUSER_ID and activity.team_id and activity.user_id and activity.user_id not in activity.team_id.with_context(active_test=False).member_ids ): raise ValidationError( - _( + self.env._( "The assigned user %(user_name)s is " "not member of the team %(team_name)s.", user_name=activity.user_id.name, diff --git a/mail_activity_team/models/mail_activity_mixin.py b/mail_activity_team/models/mail_activity_mixin.py index d24c6af9c..af79770f9 100644 --- a/mail_activity_team/models/mail_activity_mixin.py +++ b/mail_activity_team/models/mail_activity_mixin.py @@ -19,7 +19,7 @@ def _compute_activity_team_user_ids(self): rec.activity_team_user_ids = rec.activity_ids.mapped("team_id.member_ids") def _search_my_activity_date_deadline(self, operator, operand): - if not self._context.get("team_activities", False): + if not self.env.context.get("team_activities", False): return super()._search_my_activity_date_deadline(operator, operand) activity_ids = self.env["mail.activity"]._search( [ @@ -44,6 +44,13 @@ def activity_schedule( user-team missmatch. We can hook onto `act_values` dict as it's passed to the create activity method. """ + # Pick up some defaults from mail.activity.schedule + for field in ("team_id", "team_user_id", "user_id"): + if self.env.context.get(f"schedule_default_{field}") and not act_values.get( + field + ): + act_values[field] = self.env.context[f"schedule_default_{field}"] + if self.env.context.get("force_activity_team"): act_values["team_id"] = self.env.context["force_activity_team"].id if "team_id" not in act_values: @@ -64,17 +71,6 @@ def activity_schedule( act_values.update( {"user_id": activity_type.default_team_id.member_ids[:1].id} ) - else: - user_id = act_values.get("user_id") - if user_id: - team = ( - self.env["mail.activity"] - .with_context( - default_res_model=self._name, - ) - ._get_default_team_id(user_id=user_id) - ) - act_values.update({"team_id": team.id}) return super().activity_schedule( act_type_xmlid=act_type_xmlid, date_deadline=date_deadline, diff --git a/mail_activity_team/models/mail_activity_plan_template.py b/mail_activity_team/models/mail_activity_plan_template.py new file mode 100644 index 000000000..d6e8e41d6 --- /dev/null +++ b/mail_activity_team/models/mail_activity_plan_template.py @@ -0,0 +1,95 @@ +from odoo import api, fields, models +from odoo.exceptions import ValidationError + + +class MailActivityPlanTemplate(models.Model): + _inherit = "mail.activity.plan.template" + + activity_team_user_id = fields.Many2one( + comodel_name="res.users", + compute="_compute_activity_team_user_id", + readonly=False, + help="The team member that the activity will be assigned to specifically", + store=True, + string="Team user", + ) + activity_team_id = fields.Many2one( + comodel_name="mail.activity.team", + compute="_compute_activity_team_id", + ondelete="restrict", + readonly=False, + store=True, + string="Team assigned to", + ) + activity_team_required = fields.Boolean( + compute="_compute_activity_team_required", + help="Indicate if this plan template must have an activity team", + ) + # Add compute method to existing field + responsible_id = fields.Many2one( + compute="_compute_responsible_id", + readonly=False, + store=True, + ) + responsible_type = fields.Selection( + ondelete={"team": "set default"}, + selection_add=[("team", "Team")], + ) + + @api.depends("responsible_type") + def _compute_activity_team_required(self): + """Hook to override requiredness of activity team""" + for template in self: + template.activity_team_required = template.responsible_type == "team" + + @api.depends("activity_team_id", "responsible_type") + def _compute_activity_team_user_id(self): + """Ensure consistency between the activity team and the team user""" + for template in self: + user = template.activity_team_user_id + if template.activity_team_required: + team = template.activity_team_id + if team: + if not user or user not in team.member_ids: + if team.user_id: + template.activity_team_user_id = team.user_id + elif len(team.member_ids) == 1: + template.activity_team_user_id = team.member_ids + elif user: + template.activity_team_user_id = False + elif user: + template.activity_team_user_id = False + elif user: + template.activity_team_user_id = False + + @api.depends("activity_type_id", "responsible_type") + def _compute_activity_team_id(self): + """Assign the default team from the activity type""" + for template in self: + if template.activity_team_required: + if template.activity_type_id.default_team_id: + template.activity_team_id = ( + template.activity_type_id.default_team_id + ) + elif template.activity_team_id: + template.activity_team_id = False + + @api.depends("responsible_type") + def _compute_responsible_id(self): + """Wipe responsible if field is not visible (c.q. allowed)""" + for template in self: + if template.activity_team_required and template.responsible_id: + template.responsible_id = False + + @api.constrains("responsible_type", "activity_team_id") + def _check_activity_team(self): + for template in self: + if template.activity_team_required and not template.activity_team_id: + raise ValidationError(self.env._("Please enter an activity team.")) + + def _determine_responsible(self, on_demand_responsible, applied_on_record): + # Avoid signalling an error for a 'team' template without a user. + self.ensure_one() + if self.activity_team_required: + return {"error": False} + return super()._determine_responsible(on_demand_responsible, applied_on_record) diff --git a/mail_activity_team/models/mail_activity_team.py b/mail_activity_team/models/mail_activity_team.py index 6c6a71c50..88cd01cd6 100644 --- a/mail_activity_team/models/mail_activity_team.py +++ b/mail_activity_team/models/mail_activity_team.py @@ -52,9 +52,7 @@ def _compute_missing_activities(self): @api.onchange("user_id") def _onchange_user_id(self): if self.user_id and self.user_id not in self.member_ids: - members_ids = self.member_ids.ids - members_ids.append(self.user_id.id) - self.member_ids = [(4, member) for member in members_ids] + self.member_ids += self.user_id def assign_team_to_unassigned_activities(self): activity_model = self.env["mail.activity"] diff --git a/mail_activity_team/readme/CREDITS.md b/mail_activity_team/readme/CREDITS.md index 268326161..e69de29bb 100644 --- a/mail_activity_team/readme/CREDITS.md +++ b/mail_activity_team/readme/CREDITS.md @@ -1 +0,0 @@ -The migration of this module from 16.0 to 17.0 was financially supported by Camptocamp diff --git a/mail_activity_team/readme/USAGE.md b/mail_activity_team/readme/USAGE.md index 3da67bd8e..e0729e6af 100644 --- a/mail_activity_team/readme/USAGE.md +++ b/mail_activity_team/readme/USAGE.md @@ -12,5 +12,8 @@ Teams. When you create a new activity the application will propose the user's assigned team. +When creating activity plans, instead of assigning an activity to a user, there +is also the option to assign it to a team instead. + You can report on the activities assigned to a team going to *Dashboards / Activities*, and then filter by a specific team or group by teams. diff --git a/mail_activity_team/security/mail_activity_team_security.xml b/mail_activity_team/security/mail_activity_team_security.xml index ece5bff24..f62afb42d 100644 --- a/mail_activity_team/security/mail_activity_team_security.xml +++ b/mail_activity_team/security/mail_activity_team_security.xml @@ -6,7 +6,7 @@ [('team_id', 'in', user.activity_team_ids.ids)] - + diff --git a/mail_activity_team/static/description/index.html b/mail_activity_team/static/description/index.html index f00a68aeb..12f550500 100644 --- a/mail_activity_team/static/description/index.html +++ b/mail_activity_team/static/description/index.html @@ -374,7 +374,7 @@

Mail Activity Team

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:ca0203ad2f0fed4e4686b319424332ac44446e2380683a802c1052f78584cfa4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module adds the possibility to assign teams to activities.

Table of contents

@@ -404,6 +404,8 @@

Usage

Teams.

When you create a new activity the application will propose the user’s assigned team.

+

When creating activity plans, instead of assigning an activity to a +user, there is also the option to assign it to a team instead.

You can report on the activities assigned to a team going to Dashboards / Activities, and then filter by a specific team or group by teams.

@@ -412,7 +414,7 @@

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 to smash it by providing a detailed and welcomed -feedback.

+feedback.

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

@@ -460,8 +462,6 @@

Contributors

Other credits

-

The migration of this module from 16.0 to 17.0 was financially supported -by Camptocamp

Maintainers

@@ -472,7 +472,7 @@

Maintainers

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/mail project on GitHub.

+

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

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

diff --git a/mail_activity_team/static/src/core/web/activity.xml b/mail_activity_team/static/src/core/web/activity.xml index 50455e416..00da3bf6c 100644 --- a/mail_activity_team/static/src/core/web/activity.xml +++ b/mail_activity_team/static/src/core/web/activity.xml @@ -6,20 +6,6 @@ t-inherit="mail.Activity" t-inherit-mode="extension" > - - - props.activity.user_id - - - - props.activity.user_id - (Team ) - - - props.activity.user_id - diff --git a/mail_activity_team/static/src/models/activity_menu.esm.js b/mail_activity_team/static/src/models/activity_menu.esm.js index 142417287..c53cf2254 100644 --- a/mail_activity_team/static/src/models/activity_menu.esm.js +++ b/mail_activity_team/static/src/models/activity_menu.esm.js @@ -1,6 +1,7 @@ import {ActivityMenu} from "@mail/core/web/activity_menu"; import {patch} from "@web/core/utils/patch"; import {useRef} from "@odoo/owl"; +import {useService} from "@web/core/utils/hooks"; import {user} from "@web/core/user"; patch(ActivityMenu.prototype, { @@ -8,6 +9,7 @@ patch(ActivityMenu.prototype, { super.setup(); this.currentFilter = "my"; this.rootRef = useRef("mail_activity_team_dropdown"); + this.store = useService("mail.store"); }, activateFilter(filter_el) { this.deactivateButtons(); @@ -15,7 +17,7 @@ patch(ActivityMenu.prototype, { filter_el.classList.add("active"); this.currentFilter = filter_el.dataset.filter; this.updateTeamActivitiesContext(); - this.store.fetchData({systray_get_activities: true}); + this.store.fetchStoreData("systray_get_activities"); }, updateTeamActivitiesContext() { var active = false; @@ -30,7 +32,9 @@ patch(ActivityMenu.prototype, { }, deactivateButtons() { - this.rootRef.el.querySelector(".o_filter_nav_item").classList.remove("active"); + this.rootRef.el.querySelectorAll(".o_filter_nav_item").forEach((el) => { + el.classList.remove("active"); + }); }, onClickActivityFilter(filter) { this.activateFilter(this.rootRef.el.querySelector("." + filter)); diff --git a/mail_activity_team/tests/__init__.py b/mail_activity_team/tests/__init__.py index f4a7f5950..2ebbcd085 100644 --- a/mail_activity_team/tests/__init__.py +++ b/mail_activity_team/tests/__init__.py @@ -1 +1,2 @@ from . import test_mail_activity_team +from . import test_mail_activity diff --git a/mail_activity_team/tests/test_mail_activity.py b/mail_activity_team/tests/test_mail_activity.py new file mode 100644 index 000000000..5921abd38 --- /dev/null +++ b/mail_activity_team/tests/test_mail_activity.py @@ -0,0 +1,295 @@ +from odoo import Command +from odoo.tests import Form, users + +from odoo.addons.base.tests.common import BaseCommon + + +class TestMailActivity(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + + # Create Users + cls.user = cls.env["res.users"].create( + { + "company_id": cls.env.ref("base.main_company").id, + "name": "Employee", + "login": "csu", + "email": "crmuser@yourcompany.com", + "group_ids": [ + Command.set( + [ + cls.env.ref("base.group_user").id, + cls.env.ref("base.group_partner_manager").id, + ] + ) + ], + } + ) + cls.user2 = cls.env["res.users"].create( + { + "company_id": cls.env.ref("base.main_company").id, + "name": "Employee 2", + "login": "csu2", + "email": "crmuser2@yourcompany.com", + "group_ids": [Command.set([cls.env.ref("base.group_user").id])], + } + ) + cls.partner_ir_model = cls.env["ir.model"]._get("res.partner") + cls.partner_client = cls.env["res.partner"].create( + { + "name": "Test Partner", + "email": "test@example.com", + "is_company": True, + } + ) + # Create Activity Types + cls.activity1 = cls.env["mail.activity.type"].create( + { + "name": "Initial Contact", + "delay_count": 5, + "delay_unit": "days", + "summary": "ACT 1 : Presentation, barbecue, ... ", + "res_model": "res.partner", + } + ) + + @users("csu") + def test_get_default_team_id_one_team_with_model(self): + """Test _get_default_team_id correctly finds team with specified model_id""" + # Create a team specific to res.partner model + team_partner = ( + self.env["mail.activity.team"] + .sudo() + .create( + { + "name": "Partner Team", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + ) + form_team_from_user = Form( + self.env["mail.activity"].with_context( + default_res_model="res.partner", + default_res_id=self.partner_client.id, + ) + ) + self.assertEqual( + form_team_from_user.team_id, + team_partner, + "Should return the team matching the model_id", + ) + activity = form_team_from_user.save() + self.assertEqual( + activity.team_id, + team_partner, + "Should return the team matching the model_id", + ) + + @users("csu") + def test_get_default_team_id_one_team_without_model_restriction(self): + """Test _get_default_team_id finds team without model restrictions""" + # Create a team without model restrictions + team_generic = ( + self.env["mail.activity.team"] + .sudo() + .create( + { + "name": "Generic Team", + "res_model_ids": [Command.clear()], # No model restrictions + "member_ids": [Command.set([self.user.id])], + } + ) + ) + # Test without a model - should find the generic team + form_result_team = Form(self.env["mail.activity"]) + self.assertEqual( + form_result_team.team_id, + team_generic, + "Should return team without model restrictions", + ) + # Test with a model - still finds the generic team + form_result_team_from_model = Form( + self.env["mail.activity"].with_context( + default_res_model="res.partner", + default_res_id=self.partner_client.id, + ), + ) + self.assertEqual( + form_result_team_from_model.team_id, + team_generic, + "Should return team without model restrictions", + ) + + def test_get_default_team_id_no_match(self): + """Test _get_default_team_id returns empty when no team matches""" + # Create a team for a specific model + self.env["mail.activity.team"].sudo().create( + { + "name": "Users Team", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + # Search for a different user who is not a member + form_result_team = Form( + self.env["mail.activity"].with_context( + default_res_model="res.partner", + default_res_id=self.partner_client.id, + ) + ) + form_result_team.user_id = self.user2 + self.assertFalse( + form_result_team.team_id, + "Should return empty recordset when user is not a team member", + ) + activity = form_result_team.save() + self.assertFalse( + activity.team_id, + "Should return empty recordset when user is not a team member", + ) + + def test_get_default_team_id_priority_model_match(self): + """Test _get_default_team_id returns first matching team""" + # Create two teams for the same model and user + self.env["mail.activity.team"].create( + { + "name": "Team A", + "res_model_ids": [Command.clear()], # No model restrictions + "member_ids": [Command.set([self.user.id])], + } + ) + team_b = self.env["mail.activity.team"].create( + { + "name": "Team B", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + # Test - should return the first match (based on search order) + form_result_team = Form( + self.env["mail.activity"].with_context( + default_res_model_id=self.partner_ir_model.id, + default_res_id=self.partner_client.id, + ) + ) + form_result_team.user_id = self.user + self.assertEqual( + form_result_team.team_id, + team_b, + "Should return the team with model match", + ) + activity = form_result_team.save() + self.assertEqual( + activity.team_id, + team_b, + "Should return the team with model match", + ) + + def test_create_activity_without_team_assigns_team_by_model_and_user(self): + """Test creating activity with user_id but no team_id assigns default team""" + # Clean up existing activities + self.env["mail.activity"].search([]).unlink() + # Create a team for the partner model + team = self.env["mail.activity.team"].create( + { + "name": "Auto Assign Team", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + # Create an activity with team_user_id but no team_id + activity = self.env["mail.activity"].create( + { + "activity_type_id": self.activity1.id, + "note": "Test auto team assignment", + "res_id": self.partner_client.id, + "res_model_id": self.partner_ir_model.id, + "team_user_id": self.user.id, + } + ) + # Verify team was not assigned + self.assertEqual( + activity.team_id, + team, + "Team should be selected by model and (team) user", + ) + + def test_create_activity_without_team_assigns_correct_team(self): + """Test creating activity with user_id but no team_id assigns default team""" + # Clean up existing activities + self.env["mail.activity"].search([]).unlink() + # Create a team for the partner model + team_auto = self.env["mail.activity.team"].create( + { + "name": "Auto Assign Team", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + # Create an activity with user_id but no team_id + activity = self.env["mail.activity"].create( + { + "activity_type_id": self.activity1.id, + "note": "Test auto team assignment", + "res_id": self.partner_client.id, + "res_model_id": self.partner_ir_model.id, + "user_id": self.user.id, + } + ) + # Verify team was automatically assigned + self.assertEqual( + activity.team_id, + team_auto, + "Team should be automatically assigned based on user and model", + ) + + def test_create_activity_with_team_false(self): + """Test creating activity with user_id but no team_id assigns default team""" + # Clean up existing activities + self.env["mail.activity"].search([]).unlink() + # Create a team for the partner model + self.env["mail.activity.team"].create( + { + "name": "Auto Assign Team", + "res_model_ids": [Command.set([self.partner_ir_model.id])], + "member_ids": [Command.set([self.user.id])], + } + ) + # Create an activity with user_id but no team_id + activity = self.env["mail.activity"].create( + { + "activity_type_id": self.activity1.id, + "note": "Test auto team assignment", + "res_id": self.partner_client.id, + "res_model_id": self.partner_ir_model.id, + "team_user_id": self.user.id, + "team_id": False, # Explicitly set team_id to False + } + ) + # Verify that no team was assigned + self.assertFalse( + activity.team_id, + "Team should not be assigned when team_id is explicitly set to False", + ) + + def test_create_keeps_user_when_team_explicitly_false(self): + """Explicit team_id=False must not drop an explicit assignee.""" + activity = ( + self.env["mail.activity"] + .with_user(self.user) + .sudo() + .create( + { + "activity_type_id": self.activity1.id, + "note": "Regression check: keep explicit assignee.", + "res_id": self.partner_client.id, + "res_model_id": self.partner_ir_model.id, + "user_id": self.user2.id, + "team_id": False, + } + ) + ) + self.assertFalse(activity.team_id) + self.assertEqual(activity.user_id, self.user2) diff --git a/mail_activity_team/tests/test_mail_activity_team.py b/mail_activity_team/tests/test_mail_activity_team.py index 4a20b4039..8148a4112 100644 --- a/mail_activity_team/tests/test_mail_activity_team.py +++ b/mail_activity_team/tests/test_mail_activity_team.py @@ -1,10 +1,9 @@ # Copyright 2018-22 ForgeFlow S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -import os from datetime import date from odoo.exceptions import ValidationError -from odoo.modules.migration import load_script +from odoo.fields import Command from odoo.tests import Form from odoo.tests.common import TransactionCase @@ -23,10 +22,8 @@ def setUpClass(cls): "name": "Employee", "login": "csu", "email": "crmuser@yourcompany.com", - "groups_id": [ - ( - 6, - 0, + "group_ids": [ + Command.set( [ cls.env.ref("base.group_user").id, cls.env.ref("base.group_partner_manager").id, @@ -41,7 +38,7 @@ def setUpClass(cls): "name": "Employee 2", "login": "csu2", "email": "crmuser2@yourcompany.com", - "groups_id": [(6, 0, [cls.env.ref("base.group_user").id])], + "group_ids": [Command.set([cls.env.ref("base.group_user").id])], } ) cls.employee3 = cls.env["res.users"].create( @@ -50,7 +47,7 @@ def setUpClass(cls): "name": "Employee 3", "login": "csu3", "email": "crmuser3@yourcompany.com", - "groups_id": [(6, 0, [cls.env.ref("base.group_user").id])], + "group_ids": [Command.set([cls.env.ref("base.group_user").id])], } ) # Create Activity Types @@ -73,7 +70,11 @@ def setUpClass(cls): } ) # Create Teams and Activities - cls.partner_client = cls.env.ref("base.res_partner_1") + cls.partner_client = cls.env["res.partner"].create( + { + "name": "Test Client", + } + ) cls.partner_ir_model = cls.env["ir.model"]._get("res.partner") cls.act1 = ( cls.env["mail.activity"] @@ -91,15 +92,15 @@ def setUpClass(cls): cls.team1 = cls.env["mail.activity.team"].create( { "name": "Team 1", - "res_model_ids": [(6, 0, [cls.partner_ir_model.id])], - "member_ids": [(6, 0, [cls.employee.id])], + "res_model_ids": [Command.set([cls.partner_ir_model.id])], + "member_ids": [Command.set([cls.employee.id])], } ) cls.team2 = cls.env["mail.activity.team"].create( { "name": "Team 2", - "res_model_ids": [(6, 0, [cls.partner_ir_model.id])], - "member_ids": [(6, 0, [cls.employee.id, cls.employee2.id])], + "res_model_ids": [Command.set([cls.partner_ir_model.id])], + "member_ids": [Command.set([cls.employee.id, cls.employee2.id])], } ) cls.act2 = ( @@ -298,7 +299,8 @@ def test_activity_count(self): self.assertEqual(res[0]["total_count"], 1) self.assertEqual(res[0]["today_count"], 2) res = self.env["res.users"].with_user(self.employee.id)._get_activity_groups() - self.assertEqual(res[0]["total_count"], 2) + # In v19 _get_activity_groups() function, groups count for each state. + self.assertEqual(res[0]["total_count"], 1) def test_activity_schedule_next(self): self.activity1.write( @@ -318,6 +320,62 @@ def test_activity_schedule_next(self): # As we are in a 'team activity' context, the user should not be set self.assertEqual(next_activities.user_id, self.env["res.users"]) + def test_mail_activity_schedule_wizard(self): + self.activity1.default_team_id = self.team1 + wizard_form = Form( + self.env["mail.activity.schedule"].with_context( + active_ids=self.partner_client.ids, + active_model=self.partner_client._name, + ) + ) + wizard_form.activity_type_id = self.activity1 + # The activity's default team is set, and its member is the assigned user + self.assertEqual(wizard_form.activity_team_id, self.team1) + self.assertEqual(wizard_form.activity_team_user_id, self.employee) + + # Assign a team with a default member + self.team2.user_id = self.employee2 + wizard_form.activity_team_id = self.team2 + # Original team user is kept because it is also a member of the new team + self.assertEqual(wizard_form.activity_team_user_id, self.employee) + + # Reset some values and assign the team with the default user again + wizard_form.activity_team_user_id = self.env["res.users"] + wizard_form.activity_team_id = self.team2 + # Now the team user is the default user of the team + self.assertEqual(wizard_form.activity_team_user_id, self.employee2) + + other_team = self.env["mail.activity.team"].create( + { + "name": "Team 3", + "member_ids": [ + Command.link(self.employee.id), + Command.link(self.employee3.id), + ], + }, + ) + wizard_form.activity_team_id = other_team + # Employee 2 is not a member of the new team, so team user is reset + self.assertFalse(wizard_form.activity_team_user_id) + + # Set one of the members of the team and schedule the activity + wizard_form.activity_team_user_id = self.employee3 + + activities = self.partner_client.activity_ids + # Schedule the activity + wizard_form.save().action_schedule_activities() + activity = self.partner_client.activity_ids - activities + self.assertRecordValues( + activity, + [ + { + "activity_type_id": self.activity1.id, + "team_id": other_team.id, + "user_id": self.employee3.id, + }, + ], + ) + def test_schedule_activity_from_server_action(self): partner = self.env["res.partner"].create({"name": "Test Partner"}) action = self.env["ir.actions.server"].create( @@ -393,7 +451,7 @@ def test_web_search_read(self): # Create a non-team activity for our second employee, for a second partner self.team1.member_ids |= self.employee2 partner2 = self.partner_client.copy() - self.employee2.groups_id += self.env.ref("base.group_partner_manager") + self.employee2.group_ids += self.env.ref("base.group_partner_manager") # Craft the activity without a team act3 = ( @@ -430,20 +488,177 @@ def test_web_search_read(self): set(self.partner_client.ids), ) - def test_migration(self): - """Check that the 18.0.1.0.0 migration script runs without error""" - rule = self.env.ref("mail_activity_team.mail_activity_rule_my_team") - rule.perm_create = True + def test_mail_activity_plan_ui_logic(self): + """Check team/team user consistency in plan template view""" + plan = self.env["mail.activity.plan"].create( + { + "name": __name__, + "res_model": "res.partner", + } + ) + self.activity1.default_team_id = self.team1 + template = self.env["mail.activity.plan.template"].create( + { + "summary": __name__, + "responsible_type": "other", + "responsible_id": self.employee3.id, + "activity_type_id": self.activity1.id, + "plan_id": plan.id, + "sequence": 1, + "delay_count": 1, + } + ) + # Team is not set by default + self.assertFalse(template.activity_team_id) + # If template is set to assign to team, default team of the activity is set + template.responsible_type = "team" + self.assertEqual(template.activity_team_id, self.team1) + + # Can't just remove the team without changing the assignment type + with self.assertRaisesRegex( + ValidationError, + "Please enter an activity team", + ): + with self.env.cr.savepoint(): + template.activity_team_id = False - # Run the migration script - pyfile = os.path.join( - "mail_activity_team", - "migrations", - "18.0.1.0.0", - "post-migration.py", + # Team is reset if type is not team + template.write( + { + "responsible_type": "other", + "responsible_id": self.env.user.id, + }, ) - name, ext = os.path.splitext(os.path.basename(pyfile)) - mod = load_script(pyfile, name) - mod.migrate(self.env.cr, "18.0.1.0.0") + self.assertFalse(template.activity_team_id) - self.assertFalse(rule.perm_create) + # The default team user is set to the only member of the team + template.write( + { + "responsible_type": "team", + "activity_team_id": self.team1.id, + } + ) + self.assertEqual(template.activity_team_user_id, self.employee) + # The responsible is reset if assignment is changed to team + self.assertFalse(template.responsible_id) + # Assign a team with a default member + self.team2.user_id = self.employee2 + template.activity_team_id = self.team2 + # Original team user is kept because it is also a member of the new team + self.assertEqual(template.activity_team_user_id, self.employee) + # Team user is reset if team is reset + template.write( + { + "responsible_type": "other", + "responsible_id": self.env.user.id, + "activity_team_id": False, + }, + ) + self.assertFalse(template.activity_team_user_id) + # Assign the team with the default user again + template.write( + { + "responsible_type": "team", + "activity_team_id": self.team2.id, + }, + ) + # Now the team user is the default user of the team + self.assertEqual(template.activity_team_user_id, self.employee2) + + other_team = self.env["mail.activity.team"].create( + { + "name": "Team 3", + "member_ids": [ + Command.link(self.employee.id), + Command.link(self.employee3.id), + ], + }, + ) + template.activity_team_id = other_team + # Employee 2 is not a member of the new team, so team user is reset + self.assertFalse(template.activity_team_user_id) + + def test_mail_activity_plan(self): + """Activities for teams can be scheduled using an activity plan""" + plan = self.env["mail.activity.plan"].create( + { + "name": __name__, + "res_model": "res.partner", + } + ) + self.env["mail.activity.plan.template"].create( + { + "summary": __name__, + "responsible_type": "other", + "responsible_id": self.employee3.id, + "activity_type_id": self.activity1.id, + "plan_id": plan.id, + "sequence": 1, + "delay_count": 1, + } + ) + self.env["mail.activity.plan.template"].create( + { + "summary": __name__, + "responsible_type": "team", + "activity_team_id": self.team1.id, + "activity_type_id": self.activity2.id, + "plan_id": plan.id, + "sequence": 2, + "delay_count": 2, + } + ) + activities = self.partner_client.activity_ids + + wizard = ( + self.env["mail.activity.schedule"] + .with_context( + active_ids=self.partner_client.ids, + active_model=self.partner_client._name, + ) + .create( + { + "plan_id": plan.id, + "plan_date": date.today(), + } + ) + ) + wizard.action_schedule_plan() + new_activities = self.partner_client.activity_ids - activities + self.assertRecordValues( + new_activities, + [ + { + "activity_type_id": self.activity2.id, + "team_id": self.team1.id, + "user_id": False, + }, + { + "activity_type_id": self.activity1.id, + "team_id": False, + "user_id": self.employee3.id, + }, + ], + ) + + # Coverage: _plan_filter_activity_templates_to_schedule will still + # return both activities if called without special context key + self.assertEqual( + wizard._plan_filter_activity_templates_to_schedule(), + plan.template_ids, + ) + # or when upper frame inspection fails + with self.assertLogs( + "odoo.addons.mail_activity_team.wizard.mail_activity_schedule", + level="WARNING", + ) as log_catcher: + self.assertEqual( + wizard.with_context( + fire_team_activities=True, + )._plan_filter_activity_templates_to_schedule(), + plan.template_ids, + ) + self.assertIn( + "Could not find 'activity_descriptions' list in inspected frames", + log_catcher.output[0], + ) diff --git a/mail_activity_team/views/mail_activity_plan_template_views.xml b/mail_activity_team/views/mail_activity_plan_template_views.xml new file mode 100644 index 000000000..cf9a2e093 --- /dev/null +++ b/mail_activity_team/views/mail_activity_plan_template_views.xml @@ -0,0 +1,24 @@ + + + + + mail.activity.plan.template + + + + + + + + diff --git a/mail_activity_team/views/mail_activity_plan_views.xml b/mail_activity_team/views/mail_activity_plan_views.xml new file mode 100644 index 000000000..e6c95b13b --- /dev/null +++ b/mail_activity_team/views/mail_activity_plan_views.xml @@ -0,0 +1,15 @@ + + + + + mail.activity.plan + + + + + + + diff --git a/mail_activity_team/views/mail_activity_views.xml b/mail_activity_team/views/mail_activity_views.xml index 07fb47f3a..6aa89acd3 100644 --- a/mail_activity_team/views/mail_activity_views.xml +++ b/mail_activity_team/views/mail_activity_views.xml @@ -54,7 +54,7 @@ - + diff --git a/mail_activity_team/wizard/mail_activity_schedule.py b/mail_activity_team/wizard/mail_activity_schedule.py index c8a18eed1..710e26c7b 100644 --- a/mail_activity_team/wizard/mail_activity_schedule.py +++ b/mail_activity_team/wizard/mail_activity_schedule.py @@ -1,8 +1,13 @@ # Copyright 2024 Camptocamp SA # Copyright 2024 CorporateHub # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import inspect +import logging from odoo import api, fields, models +from odoo.tools.misc import format_date + +_logger = logging.getLogger(__name__) class MailActivitySchedule(models.TransientModel): @@ -25,10 +30,10 @@ def _compute_activity_team_id(self): if scheduler.activity_type_id.default_team_id: scheduler.activity_team_id = scheduler.activity_type_id.default_team_id elif not scheduler.activity_team_id: - scheduler.activity_team_id = ( - self.env["mail.activity"] - .with_context(default_res_model=scheduler.sudo().res_model_id.model) - ._get_default_team_id(user_id=scheduler.activity_team_user_id.id) + scheduler.activity_team_id = self.env[ + "mail.activity" + ]._get_default_team_id( + scheduler.activity_team_user_id.id, scheduler.sudo().res_model_id.id ) @api.onchange("activity_team_id") @@ -53,20 +58,75 @@ def _onchange_activity_team_user_id(self): and self.activity_team_user_id in self.activity_team_id.member_ids ): return - self.activity_team_id = ( - self.env["mail.activity"] - .with_context(default_res_model=self.sudo().res_model_id.model) - ._get_default_team_id(user_id=self.activity_team_user_id.id) + self.activity_team_id = self.env["mail.activity"]._get_default_team_id( + self.activity_team_user_id.id, self.sudo().res_model_id.id ) def _action_schedule_activities(self): - return self._get_applied_on_records().activity_schedule( - activity_type_id=self.activity_type_id.id, - automated=False, - summary=self.summary, - note=self.note, - user_id=self.activity_team_user_id.id, - team_user_id=self.activity_team_user_id.id, - team_id=self.activity_team_id.id, - date_deadline=self.date_deadline, + # Insert default team data which is picked up for activities that are + # created without a team already. + self = self.with_context( + schedule_default_team_id=self.activity_team_id.id, + schedule_default_team_user_id=self.activity_team_user_id.id, + schedule_default_user_id=self.activity_team_user_id.id, + ) + return super()._action_schedule_activities() + + def action_schedule_plan(self): + # Triggering scheduled team activities in + # _plan_filter_activity_templates_to_schedule which is called from the + # super method to fetch the activities that need to be scheduled. + # This is because activity parameters are determined inline in the + # super method, and the activity team cannot be inserted there in a + # clean override. + self = self.with_context(fire_team_activities=True) + return super().action_schedule_plan() + + @staticmethod + def _get_activity_schedule_plan_data(): + """Fetch some variables defined in action_schedule_plan""" + frame = inspect.currentframe() + while frame.f_back: + frame = frame.f_back + f_locals = frame.f_locals + if "activity_descriptions" in f_locals and "record" in f_locals: + return f_locals["record"], f_locals["activity_descriptions"] + _logger.warning( + "Could not find 'activity_descriptions' list in inspected frames" ) + return None, None + + def _plan_filter_activity_templates_to_schedule(self): + # Instead of returning all templates, including those with a team, + # go ahead and schedule only those with a team and only return + # the remaining activity templates. + res = super()._plan_filter_activity_templates_to_schedule() + if self.env.context.get("fire_team_activities"): + # Immediately schedule team activities + record, activity_descriptions = self._get_activity_schedule_plan_data() + if record is None: + return res + templates = res.filtered("activity_team_required") + others = res - templates + for template in templates: + date_deadline = template._get_date_deadline(self.plan_date) + record.activity_schedule( + activity_type_id=template.activity_type_id.id, + automated=False, + summary=template.summary, + note=template.note, + user_id=template.activity_team_user_id.id, + team_id=template.activity_team_id.id, + date_deadline=date_deadline, + ) + activity_descriptions.append( + self.env._( + "%(activity)s, assigned to team %(name)s, " + "due on the %(deadline)s", + activity=template.summary or template.activity_type_id.name, + name=template.activity_team_id.name, + deadline=format_date(self.env, date_deadline), + ) + ) + return others + return res From 4079fb792c4e1f5d259a9ca0b81c1a788396ee3e Mon Sep 17 00:00:00 2001 From: Muaaz Siddiq Date: Tue, 14 Apr 2026 13:06:40 +0200 Subject: [PATCH 81/81] [FIX] mail_activity_team: Fix test --- mail_activity_team/models/mail_activity_plan_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_activity_team/models/mail_activity_plan_template.py b/mail_activity_team/models/mail_activity_plan_template.py index d6e8e41d6..787546e1c 100644 --- a/mail_activity_team/models/mail_activity_plan_template.py +++ b/mail_activity_team/models/mail_activity_plan_template.py @@ -91,5 +91,5 @@ def _determine_responsible(self, on_demand_responsible, applied_on_record): # Avoid signalling an error for a 'team' template without a user. self.ensure_one() if self.activity_team_required: - return {"error": False} + return {"error": False, "warning": False} return super()._determine_responsible(on_demand_responsible, applied_on_record)