[IMP] project: adjust portal visibility followers behavior

Currently, portal followers of a project and its tasks are removed when
the project visibility is changed to something else than portal.
=> We want to keep the behavior, but only when changing the visibility
from portal to something else.

When the project visibility is changed to portal, we currently add
its customer to its followers.
=> In that case, we also want to add the customer of the tasks to the
followers of the corresponding task.

When the customer of a project in portal visibility is changed, the
new customer is added to the followers of the project.
=> We want to remove this behavior.

When a project is created with a customer and the portal visibility,
the customer is added to the followers of the project.
=> We want to remove this behavior to avoid mistakenly showing a project
that is not ready yet to the customer.

This commit implements those changes, and also adds a warning when
changing the visibility of the project if that change will automatically
add/remove followers to the project and its tasks.

Related: https://github.com/odoo/enterprise/pull/25800

Task-2812551

closes odoo/odoo#87747

Related: odoo/enterprise#25800
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
This commit is contained in:
Vincent Larcin
2022-06-21 13:22:32 +02:00
parent b5f8f2133b
commit 55d8da526d
3 changed files with 37 additions and 18 deletions
+32 -18
View File
@@ -340,6 +340,7 @@ class Project(models.Model):
"When a project is shared in edit, the portal user is redirected to the kanban and list views of the tasks. They can modify a selected number of fields on the tasks.\n\n"
"In any case, an internal user with no project access rights can still access a task, "
"provided that they are given the corresponding URL (and that they are part of the followers if the project is private).")
privacy_visibility_warning = fields.Char('Privacy Visibility Warning', compute='_compute_privacy_visibility_warning')
doc_count = fields.Integer(compute='_compute_attached_docs_count', string="Number of documents attached")
date_start = fields.Date(string='Start Date')
date = fields.Date(string='Expiration Date', index=True, tracking=True)
@@ -510,6 +511,18 @@ class Project(models.Model):
for project in self:
project.collaborator_count = collaborator_count_by_project.get(project.id, 0)
@api.depends('privacy_visibility')
def _compute_privacy_visibility_warning(self):
for project in self:
if not project.ids:
project.privacy_visibility_warning = ''
elif project.privacy_visibility == 'portal' and project._origin.privacy_visibility != 'portal':
project.privacy_visibility_warning = _('Customers will be added to the followers of their project and tasks.')
elif project.privacy_visibility != 'portal' and project._origin.privacy_visibility == 'portal':
project.privacy_visibility_warning = _('Portal users will be removed from the followers of the project and its tasks.')
else:
project.privacy_visibility_warning = ''
@api.model
def _map_tasks_default_valeus(self, task, project):
""" get the default value for the copied task on project duplication """
@@ -567,9 +580,6 @@ class Project(models.Model):
# Prevent double project creation
self = self.with_context(mail_create_nosubscribe=True)
projects = super().create(vals_list)
for project in projects:
if project.privacy_visibility == 'portal' and project.partner_id:
project.message_subscribe(project.partner_id.ids)
return projects
def write(self, vals):
@@ -587,6 +597,9 @@ class Project(models.Model):
'status': vals.get('last_update_status'),
})
vals.pop('last_update_status')
if vals.get('privacy_visibility'):
self._change_privacy_visibility(vals['privacy_visibility'])
res = super(Project, self).write(vals) if vals else True
if 'allow_recurring_tasks' in vals and not vals.get('allow_recurring_tasks'):
@@ -595,11 +608,6 @@ class Project(models.Model):
if 'active' in vals:
# archiving/unarchiving a project does it on its tasks, too
self.with_context(active_test=False).mapped('tasks').write({'active': vals['active']})
if vals.get('partner_id') or vals.get('privacy_visibility'):
for project in self.filtered(lambda project: project.privacy_visibility == 'portal'):
project.message_subscribe(project.partner_id.ids)
if vals.get('privacy_visibility'):
self._change_privacy_visibility()
if 'name' in vals and self.analytic_account_id:
projects_read_group = self.env['project.project']._read_group(
[('analytic_account_id', 'in', self.analytic_account_id.ids)],
@@ -952,15 +960,23 @@ class Project(models.Model):
# Privacy
# ---------------------------------------------------
def _change_privacy_visibility(self):
def _change_privacy_visibility(self, new_visibility):
"""
Unsubscribe non-internal users from the project and tasks if the project privacy visibility
goes to a value different than 'portal'
goes from 'portal' to a different value.
If the privacy visibility is set to 'portal', subscribe back project and tasks partners.
"""
for project in self.filtered(lambda p: p.privacy_visibility != 'portal'):
portal_users = project.message_partner_ids.user_ids.filtered('share')
project.message_unsubscribe(partner_ids=portal_users.partner_id.ids)
project.mapped('tasks')._change_project_privacy_visibility()
for project in self:
if project.privacy_visibility == new_visibility:
continue
if new_visibility == 'portal':
project.message_subscribe(partner_ids=project.partner_id.ids)
for task in project.task_ids.filtered('partner_id'):
task.message_subscribe(partner_ids=task.partner_id.ids)
elif project.privacy_visibility == 'portal':
portal_users = project.message_partner_ids.user_ids.filtered('share')
project.message_unsubscribe(partner_ids=portal_users.partner_id.ids)
project.tasks._unsubscribe_portal_users()
# ---------------------------------------------------
# Project sharing
@@ -2535,10 +2551,8 @@ class Task(models.Model):
# ---------------------------------------------------
# Privacy
# ---------------------------------------------------
def _change_project_privacy_visibility(self):
for task in self.filtered(lambda t: t.project_privacy_visibility != 'portal'):
portal_users = task.message_partner_ids.user_ids.filtered('share')
task.message_unsubscribe(partner_ids=portal_users.partner_id.ids)
def _unsubscribe_portal_users(self):
self.message_unsubscribe(partner_ids=self.message_partner_ids.filtered('user_ids.share').ids)
# ---------------------------------------------------
# Analytic accounting
@@ -39,6 +39,7 @@ class TestProjectSharingCommon(TestProjectCommon):
'partner_id': cls.user_portal.partner_id.id,
'type_ids': project_sharing_stages_vals_list,
})
cls.project_portal.message_subscribe(partner_ids=[cls.partner_portal.id])
cls.task_cow = cls.env['project.task'].with_context({'mail_create_nolog': True}).create({
'name': 'Cow UserTask',
+4
View File
@@ -544,6 +544,10 @@
<field name="analytic_account_id" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]" context="{'default_partner_id': partner_id}" groups="analytic.group_analytic_accounting"/>
<field name="analytic_tag_ids" groups="analytic.group_analytic_tags" widget="many2many_tags"/>
<field name="privacy_visibility" widget="radio"/>
<span colspan="2" class="text-muted" attrs="{'invisible':[('privacy_visibility_warning', '=', '')]}">
<i class="fa fa-warning">&amp;nbsp;</i>
<field name="privacy_visibility_warning" nolabel="1"/>
</span>
</group>
<group>
<div name="alias_def" colspan="2" class="pb-2" attrs="{'invisible': [('alias_domain', '=', False)]}">