project internal users and roles changes
This commit is contained in:
parent
1d0833faf8
commit
5bce5cca2b
|
|
@ -80,6 +80,21 @@ class ProjectProject(models.Model):
|
||||||
project_stages = fields.One2many('project.stages.approval.flow', 'project_id')
|
project_stages = fields.One2many('project.stages.approval.flow', 'project_id')
|
||||||
assign_approval_flow = fields.Boolean(default=False)
|
assign_approval_flow = fields.Boolean(default=False)
|
||||||
project_sponsor = fields.Many2one('res.users')
|
project_sponsor = fields.Many2one('res.users')
|
||||||
|
allowed_project_manager_user_ids = fields.Many2many(
|
||||||
|
'res.users',
|
||||||
|
compute='_compute_portfolio_allowed_users',
|
||||||
|
string='Allowed Project Managers',
|
||||||
|
)
|
||||||
|
allowed_project_lead_user_ids = fields.Many2many(
|
||||||
|
'res.users',
|
||||||
|
compute='_compute_portfolio_allowed_users',
|
||||||
|
string='Allowed Project Leads',
|
||||||
|
)
|
||||||
|
allowed_internal_team_ids = fields.Many2many(
|
||||||
|
'internal.teams',
|
||||||
|
compute='_compute_portfolio_allowed_teams',
|
||||||
|
string='Allowed Internal Teams',
|
||||||
|
)
|
||||||
show_project_chatter = fields.Boolean(default=False)
|
show_project_chatter = fields.Boolean(default=False)
|
||||||
project_vision = fields.Text(
|
project_vision = fields.Text(
|
||||||
string="Project Vision",
|
string="Project Vision",
|
||||||
|
|
@ -1173,6 +1188,117 @@ class ProjectProject(models.Model):
|
||||||
def _default_type_ids(self):
|
def _default_type_ids(self):
|
||||||
return self._get_default_task_stage_templates()
|
return self._get_default_task_stage_templates()
|
||||||
|
|
||||||
|
def _get_role_users_for_portfolio(self, role_xmlid):
|
||||||
|
self.ensure_one()
|
||||||
|
role = self.env.ref(role_xmlid, raise_if_not_found=False)
|
||||||
|
if not role:
|
||||||
|
return self.env['res.users']
|
||||||
|
if self.portfolio_id:
|
||||||
|
assignment = self.portfolio_id.role_assignment_ids.filtered(
|
||||||
|
lambda line: line.role_id == role
|
||||||
|
)[:1]
|
||||||
|
if assignment:
|
||||||
|
return assignment.user_ids
|
||||||
|
return role.user_ids
|
||||||
|
|
||||||
|
def _get_portfolio_role_assignment(self, role_xmlid):
|
||||||
|
self.ensure_one()
|
||||||
|
role = self.env.ref(role_xmlid, raise_if_not_found=False)
|
||||||
|
if not role or not self.portfolio_id:
|
||||||
|
return self.env['project.portfolio.role.assignment']
|
||||||
|
return self.portfolio_id.role_assignment_ids.filtered(
|
||||||
|
lambda line: line.role_id == role
|
||||||
|
)[:1]
|
||||||
|
|
||||||
|
@api.depends(
|
||||||
|
'portfolio_id',
|
||||||
|
'portfolio_id.role_assignment_ids.role_id',
|
||||||
|
'portfolio_id.role_assignment_ids.user_ids',
|
||||||
|
)
|
||||||
|
def _compute_portfolio_allowed_users(self):
|
||||||
|
manager_groups = (
|
||||||
|
self.env.ref('project.group_project_manager')
|
||||||
|
| self.env.ref('project_task_timesheet_extended.group_project_supervisor')
|
||||||
|
)
|
||||||
|
for project in self:
|
||||||
|
manager_users = project._get_role_users_for_portfolio(
|
||||||
|
'project_task_timesheet_extended.role_project_manager'
|
||||||
|
)
|
||||||
|
project.allowed_project_manager_user_ids = manager_users.filtered(
|
||||||
|
lambda user: not user.share and bool(user.groups_id & manager_groups)
|
||||||
|
)
|
||||||
|
project.allowed_project_lead_user_ids = project._get_role_users_for_portfolio(
|
||||||
|
'project_task_timesheet_extended.role_project_lead'
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends('portfolio_id', 'portfolio_id.internal_team_ids')
|
||||||
|
def _compute_portfolio_allowed_teams(self):
|
||||||
|
Team = self.env['internal.teams']
|
||||||
|
fallback_teams = Team.search([('active', '=', True)])
|
||||||
|
for project in self:
|
||||||
|
project.allowed_internal_team_ids = (
|
||||||
|
project.portfolio_id.internal_team_ids
|
||||||
|
if project.portfolio_id and project.portfolio_id.internal_team_ids
|
||||||
|
else fallback_teams
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.onchange('portfolio_id')
|
||||||
|
def _onchange_portfolio_id_scope_assignments(self):
|
||||||
|
for project in self:
|
||||||
|
manager_assignment = project._get_portfolio_role_assignment(
|
||||||
|
'project_task_timesheet_extended.role_project_manager'
|
||||||
|
)
|
||||||
|
lead_assignment = project._get_portfolio_role_assignment(
|
||||||
|
'project_task_timesheet_extended.role_project_lead'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
manager_assignment
|
||||||
|
and project.user_id
|
||||||
|
and project.user_id not in project.allowed_project_manager_user_ids
|
||||||
|
):
|
||||||
|
project.user_id = False
|
||||||
|
if lead_assignment and project.project_lead:
|
||||||
|
project.project_lead &= project.allowed_project_lead_user_ids
|
||||||
|
if project.portfolio_id.internal_team_ids:
|
||||||
|
for task_stage in project.type_ids:
|
||||||
|
if task_stage.team_id and task_stage.team_id not in project.allowed_internal_team_ids:
|
||||||
|
task_stage.team_id = False
|
||||||
|
task_stage.involved_user_ids = [Command.clear()]
|
||||||
|
|
||||||
|
@api.constrains('portfolio_id', 'user_id', 'project_lead')
|
||||||
|
def _check_portfolio_role_users(self):
|
||||||
|
for project in self:
|
||||||
|
manager_assignment = project._get_portfolio_role_assignment(
|
||||||
|
'project_task_timesheet_extended.role_project_manager'
|
||||||
|
)
|
||||||
|
lead_assignment = project._get_portfolio_role_assignment(
|
||||||
|
'project_task_timesheet_extended.role_project_lead'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
manager_assignment
|
||||||
|
and project.user_id
|
||||||
|
and project.user_id not in project.allowed_project_manager_user_ids
|
||||||
|
):
|
||||||
|
raise ValidationError(_(
|
||||||
|
'The project manager must be one of the users selected for the Project Manager role on this portfolio.'
|
||||||
|
))
|
||||||
|
if lead_assignment and project.project_lead - project.allowed_project_lead_user_ids:
|
||||||
|
raise ValidationError(_(
|
||||||
|
'Project leads must be selected from the Project Lead users configured on this portfolio.'
|
||||||
|
))
|
||||||
|
|
||||||
|
@api.constrains('portfolio_id', 'type_ids', 'type_ids.team_id')
|
||||||
|
def _check_portfolio_internal_teams(self):
|
||||||
|
for project in self:
|
||||||
|
if not project.portfolio_id.internal_team_ids:
|
||||||
|
continue
|
||||||
|
invalid_stages = project.type_ids.filtered(
|
||||||
|
lambda stage: stage.team_id and stage.team_id not in project.allowed_internal_team_ids
|
||||||
|
)
|
||||||
|
if invalid_stages:
|
||||||
|
raise ValidationError(_(
|
||||||
|
'Task stage teams must be selected from the internal teams configured on this portfolio.'
|
||||||
|
))
|
||||||
|
|
||||||
project_lead = fields.Many2many(
|
project_lead = fields.Many2many(
|
||||||
"res.users",
|
"res.users",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from datetime import date, timedelta
|
from odoo.exceptions import ValidationError
|
||||||
import json
|
from datetime import date, timedelta
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class ProjectPortfolio(models.Model):
|
class ProjectPortfolio(models.Model):
|
||||||
|
|
@ -23,11 +24,25 @@ class ProjectPortfolio(models.Model):
|
||||||
|
|
||||||
description = fields.Text(string='Description')
|
description = fields.Text(string='Description')
|
||||||
|
|
||||||
project_ids = fields.One2many(
|
project_ids = fields.One2many(
|
||||||
'project.project',
|
'project.project',
|
||||||
'portfolio_id',
|
'portfolio_id',
|
||||||
string='Projects'
|
string='Projects'
|
||||||
)
|
)
|
||||||
|
internal_team_ids = fields.Many2many(
|
||||||
|
'internal.teams',
|
||||||
|
'project_portfolio_internal_team_rel',
|
||||||
|
'portfolio_id',
|
||||||
|
'team_id',
|
||||||
|
string='Internal Teams',
|
||||||
|
help='Internal teams available for projects linked to this portfolio.'
|
||||||
|
)
|
||||||
|
role_assignment_ids = fields.One2many(
|
||||||
|
'project.portfolio.role.assignment',
|
||||||
|
'portfolio_id',
|
||||||
|
string='Role Assignments',
|
||||||
|
help='Portfolio-specific users available for each project role.'
|
||||||
|
)
|
||||||
|
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
'res.company',
|
'res.company',
|
||||||
|
|
@ -533,19 +548,73 @@ class ProjectPortfolio(models.Model):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Project(models.Model):
|
class Project(models.Model):
|
||||||
_inherit = 'project.project'
|
_inherit = 'project.project'
|
||||||
|
|
||||||
portfolio_id = fields.Many2one(
|
portfolio_id = fields.Many2one(
|
||||||
'project.portfolio',
|
'project.portfolio',
|
||||||
string='Portfolio'
|
string='Portfolio'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectPortfolioRoleAssignment(models.Model):
|
||||||
class ProjectPortfolioEmployeePerformance(models.Model):
|
_name = 'project.portfolio.role.assignment'
|
||||||
|
_description = 'Project Portfolio Role Assignment'
|
||||||
|
_order = 'role_id'
|
||||||
|
|
||||||
|
portfolio_id = fields.Many2one(
|
||||||
|
'project.portfolio',
|
||||||
|
string='Portfolio',
|
||||||
|
required=True,
|
||||||
|
ondelete='cascade',
|
||||||
|
)
|
||||||
|
role_id = fields.Many2one(
|
||||||
|
'project.role',
|
||||||
|
string='Role',
|
||||||
|
required=True,
|
||||||
|
ondelete='cascade',
|
||||||
|
)
|
||||||
|
master_user_ids = fields.Many2many(
|
||||||
|
'res.users',
|
||||||
|
related='role_id.user_ids',
|
||||||
|
string='Master Assigned Users',
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
|
user_ids = fields.Many2many(
|
||||||
|
'res.users',
|
||||||
|
'project_portfolio_role_user_rel',
|
||||||
|
'assignment_id',
|
||||||
|
'user_id',
|
||||||
|
string='Portfolio Users',
|
||||||
|
domain="[('id', 'in', master_user_ids)]",
|
||||||
|
help='Users selected for this role in this portfolio.'
|
||||||
|
)
|
||||||
|
|
||||||
|
_sql_constraints = [
|
||||||
|
(
|
||||||
|
'portfolio_role_unique',
|
||||||
|
'unique(portfolio_id, role_id)',
|
||||||
|
'Each role can only be configured once per portfolio.',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.onchange('role_id')
|
||||||
|
def _onchange_role_id(self):
|
||||||
|
for assignment in self:
|
||||||
|
assignment.user_ids &= assignment.role_id.user_ids
|
||||||
|
|
||||||
|
@api.constrains('role_id', 'user_ids')
|
||||||
|
def _check_user_ids_in_role_master(self):
|
||||||
|
for assignment in self:
|
||||||
|
if assignment.user_ids - assignment.role_id.user_ids:
|
||||||
|
raise ValidationError(_(
|
||||||
|
'Portfolio users must be selected from the users assigned on the role master.'
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectPortfolioEmployeePerformance(models.Model):
|
||||||
_name = 'project.portfolio.employee.performance'
|
_name = 'project.portfolio.employee.performance'
|
||||||
_description = 'Project Portfolio Employee Performance'
|
_description = 'Project Portfolio Employee Performance'
|
||||||
_order = 'time_variance_percent desc'
|
_order = 'time_variance_percent desc'
|
||||||
|
|
||||||
portfolio_id = fields.Many2one(
|
portfolio_id = fields.Many2one(
|
||||||
|
|
@ -633,4 +702,4 @@ class ProjectPortfolioEmployeePerformance(models.Model):
|
||||||
@api.depends('total_estimated_hours', 'total_actual_hours')
|
@api.depends('total_estimated_hours', 'total_actual_hours')
|
||||||
def _compute_time_variance(self):
|
def _compute_time_variance(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
record.time_variance = record.total_actual_hours - record.total_estimated_hours
|
record.time_variance = record.total_actual_hours - record.total_estimated_hours
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@ class TaskStages(models.Model):
|
||||||
string='Team Users',
|
string='Team Users',
|
||||||
compute='_compute_team_related_user_ids',
|
compute='_compute_team_related_user_ids',
|
||||||
)
|
)
|
||||||
|
allowed_internal_team_ids = fields.Many2many(
|
||||||
|
'internal.teams',
|
||||||
|
compute='_compute_allowed_internal_team_ids',
|
||||||
|
string='Allowed Internal Teams',
|
||||||
|
)
|
||||||
is_workflow_template = fields.Boolean(
|
is_workflow_template = fields.Boolean(
|
||||||
string='Workflow Template Stage',
|
string='Workflow Template Stage',
|
||||||
default=False,
|
default=False,
|
||||||
|
|
@ -42,6 +47,22 @@ class TaskStages(models.Model):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.team_related_user_ids = rec.team_id.all_members_ids | rec.team_id.team_lead
|
rec.team_related_user_ids = rec.team_id.all_members_ids | rec.team_id.team_lead
|
||||||
|
|
||||||
|
@api.depends('project_ids', 'project_ids.portfolio_id', 'project_ids.portfolio_id.internal_team_ids')
|
||||||
|
@api.depends_context('project_stage_project_id', 'default_project_id')
|
||||||
|
def _compute_allowed_internal_team_ids(self):
|
||||||
|
Team = self.env['internal.teams']
|
||||||
|
fallback_teams = Team.search([('active', '=', True)])
|
||||||
|
context_project = self.env['project.project'].browse(
|
||||||
|
self.env.context.get('project_stage_project_id') or self.env.context.get('default_project_id')
|
||||||
|
)
|
||||||
|
for rec in self:
|
||||||
|
project = context_project or rec.project_ids[:1]
|
||||||
|
rec.allowed_internal_team_ids = (
|
||||||
|
project.portfolio_id.internal_team_ids
|
||||||
|
if project and project.portfolio_id.internal_team_ids
|
||||||
|
else fallback_teams
|
||||||
|
)
|
||||||
|
|
||||||
def _is_project_owned_stage(self, project):
|
def _is_project_owned_stage(self, project):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ access_project_cancel_hold_wizard_supervisor,access.project.cancel.hold.wizard.s
|
||||||
access_project_cancel_hold_wizard_manager,access.project.cancel.hold.wizard.manager,model_project_cancel_hold_wizard,project.group_project_manager,1,1,1,1
|
access_project_cancel_hold_wizard_manager,access.project.cancel.hold.wizard.manager,model_project_cancel_hold_wizard,project.group_project_manager,1,1,1,1
|
||||||
|
|
||||||
access_project_role_user,project.role.user,model_project_role,base.group_user,1,0,0,0
|
access_project_role_user,project.role.user,model_project_role,base.group_user,1,0,0,0
|
||||||
|
access_project_portfolio_role_assignment_user,project.portfolio.role.assignment.user,model_project_portfolio_role_assignment,base.group_user,1,1,1,0
|
||||||
|
|
||||||
access_project_portfolio_user,project.portfolio.user,model_project_portfolio,base.group_user,1,1,1,0
|
access_project_portfolio_user,project.portfolio.user,model_project_portfolio,base.group_user,1,1,1,0
|
||||||
access_project_portfolio_manager,project.portfolio.manager,model_project_portfolio,project.group_project_manager,1,1,1,1
|
access_project_portfolio_manager,project.portfolio.manager,model_project_portfolio,project.group_project_manager,1,1,1,1
|
||||||
|
access_project_portfolio_role_assignment_manager,project.portfolio.role.assignment.manager,model_project_portfolio_role_assignment,project.group_project_manager,1,1,1,1
|
||||||
|
|
||||||
access_project_role_manager,project.role.manager,model_project_role,project.group_project_manager,1,1,1,1
|
access_project_role_manager,project.role.manager,model_project_role,project.group_project_manager,1,1,1,1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
|
@ -17,12 +17,18 @@
|
||||||
<attribute name="invisible">0</attribute>
|
<attribute name="invisible">0</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
<xpath expr="//field[@name='user_id']" position="after">
|
<xpath expr="//field[@name='user_id']" position="after">
|
||||||
<field name="project_lead" widget="many2many_avatar_user"/>
|
<field name="project_lead"
|
||||||
</xpath>
|
widget="many2many_avatar_user"
|
||||||
<xpath expr="//field[@name='user_id']" position="replace">
|
domain="[('id', 'in', allowed_project_lead_user_ids)]"
|
||||||
<field name="user_id" widget="user_timeline"/>
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='user_id']" position="replace">
|
||||||
|
<field name="user_id"
|
||||||
|
widget="user_timeline"
|
||||||
|
domain="[('id', 'in', allowed_project_manager_user_ids)]"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//page[@name='settings']" position="inside">
|
<xpath expr="//page[@name='settings']" position="inside">
|
||||||
<group>
|
<group>
|
||||||
<group name="group_project_channel_managment" string="Project Channel" col="1"
|
<group name="group_project_channel_managment" string="Project Channel" col="1"
|
||||||
|
|
@ -85,6 +91,9 @@
|
||||||
<field name="enable_budget_summary" invisible="1"/>
|
<field name="enable_budget_summary" invisible="1"/>
|
||||||
<field name="can_edit_stage_in_approval" invisible="1"/>
|
<field name="can_edit_stage_in_approval" invisible="1"/>
|
||||||
<field name="active_sprint_id" invisible="1"/>
|
<field name="active_sprint_id" invisible="1"/>
|
||||||
|
<field name="allowed_project_manager_user_ids" invisible="1"/>
|
||||||
|
<field name="allowed_project_lead_user_ids" invisible="1"/>
|
||||||
|
<field name="allowed_internal_team_ids" invisible="1"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//div[@name='button_box']" position="inside">
|
<xpath expr="//div[@name='button_box']" position="inside">
|
||||||
<button class="oe_stat_button" type="object" name="action_open_sprint_backlog"
|
<button class="oe_stat_button" type="object" name="action_open_sprint_backlog"
|
||||||
|
|
@ -130,7 +139,10 @@
|
||||||
<list editable="bottom" open_form_view="True" delete="0">
|
<list editable="bottom" open_form_view="True" delete="0">
|
||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="team_id" string="Assigned Team"/>
|
<field name="team_id"
|
||||||
|
string="Assigned Team"
|
||||||
|
domain="[('id', 'in', parent.allowed_internal_team_ids)]"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
<field name="responsible_user_id" string="Responsible User" readonly="1"/>
|
<field name="responsible_user_id" string="Responsible User" readonly="1"/>
|
||||||
<field name="approval_by" string="Approval Owner"/>
|
<field name="approval_by" string="Approval Owner"/>
|
||||||
<field name="fold"/>
|
<field name="fold"/>
|
||||||
|
|
|
||||||
|
|
@ -144,10 +144,33 @@
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="Projects" invisible="project_count == 0">
|
<page string="Internal Teams">
|
||||||
<field name="project_ids">
|
<field name="internal_team_ids"
|
||||||
<list>
|
widget="many2many_tags"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page string="Portfolio Roles">
|
||||||
|
<field name="role_assignment_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="role_id"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="master_user_ids"
|
||||||
|
widget="many2many_tags"
|
||||||
|
readonly="1"
|
||||||
|
optional="show"/>
|
||||||
|
<field name="user_ids"
|
||||||
|
widget="many2many_tags"
|
||||||
|
domain="[('id', 'in', master_user_ids)]"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page string="Projects" invisible="project_count == 0">
|
||||||
|
<field name="project_ids">
|
||||||
|
<list>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="partner_id"/>
|
<field name="partner_id"/>
|
||||||
<field name="user_id" widget="user_timeline"/>
|
<field name="user_id" widget="user_timeline"/>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
<field name="inherit_id" ref="project.task_type_edit"/>
|
<field name="inherit_id" ref="project.task_type_edit"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//field[@name='fold']" position="after">
|
<xpath expr="//field[@name='fold']" position="after">
|
||||||
<field name="team_id"/>
|
<field name="allowed_internal_team_ids" invisible="1"/>
|
||||||
|
<field name="team_id"
|
||||||
|
domain="[('id', 'in', allowed_internal_team_ids)]"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
<field name="responsible_user_id"/>
|
<field name="responsible_user_id"/>
|
||||||
<field name="approval_by"/>
|
<field name="approval_by"/>
|
||||||
<field name="team_related_user_ids" invisible="1"/>
|
<field name="team_related_user_ids" invisible="1"/>
|
||||||
|
|
@ -22,7 +25,11 @@
|
||||||
<field name="inherit_id" ref="project.task_type_tree"/>
|
<field name="inherit_id" ref="project.task_type_tree"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//field[@name='name']" position="after">
|
<xpath expr="//field[@name='name']" position="after">
|
||||||
<field name="team_id" optional="show"/>
|
<field name="allowed_internal_team_ids" invisible="1"/>
|
||||||
|
<field name="team_id"
|
||||||
|
optional="show"
|
||||||
|
domain="[('id', 'in', allowed_internal_team_ids)]"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True, 'no_quick_create': True}"/>
|
||||||
<field name="responsible_user_id" optional="show"/>
|
<field name="responsible_user_id" optional="show"/>
|
||||||
<field name="approval_by" optional="show"/>
|
<field name="approval_by" optional="show"/>
|
||||||
<field name="team_related_user_ids" invisible="1"/>
|
<field name="team_related_user_ids" invisible="1"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue