@ -1,6 +1,5 @@ |
|||
## Module <project_tasks_from_templates> |
|||
|
|||
#### 05.06.2022 |
|||
#### 09.01.2024 |
|||
#### Version 15.0.1.0.0 |
|||
#### ADD |
|||
Initial Commit for Project Templates |
|||
- Initial Commit for Project Templates |
|||
|
@ -1,82 +0,0 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields, api, _ |
|||
|
|||
|
|||
class Project(models.Model): |
|||
_inherit = 'project.project' |
|||
|
|||
project_template_id = fields.Many2one('project.task.template') |
|||
|
|||
def create_task(self, item, parent): |
|||
vals = {'project_id': self.id, |
|||
'name': item.name, |
|||
'parent_id': parent, |
|||
'stage_id': self.env['project.task.type'].search([('sequence', '=', 1)], limit=1).id, |
|||
'user_ids': item.user_ids, |
|||
'description': item.description |
|||
} |
|||
task_id = self.env['project.task'].create(vals).id |
|||
for sub_task in item.child_ids: |
|||
self.create_task(sub_task, task_id) |
|||
|
|||
def action_create_project_from_template(self): |
|||
template_id = self.project_template_id |
|||
for item in template_id.task_ids: |
|||
self.create_task(item, False) |
|||
return { |
|||
'view_mode': 'form', |
|||
'res_model': 'project.project', |
|||
'res_id': self.id, |
|||
'type': 'ir.actions.act_window', |
|||
'context': self._context |
|||
} |
|||
|
|||
|
|||
class ProjectTaskCustom(models.Model): |
|||
_name = 'project.task.custom' |
|||
|
|||
name = fields.Char("Name", required=True) |
|||
project_template_id = fields.Many2one('project.task.template') |
|||
description = fields.Text("Task Description") |
|||
user_ids = fields.Many2many('res.users', relation='project_task_custom_user_rel', column1='task_id', |
|||
column2='user_id', |
|||
string='Assignees', tracking=True) |
|||
parent_id = fields.Many2one('project.task.custom', string='Parent Task', index=True) |
|||
child_ids = fields.One2many('project.task.custom', 'parent_id', string="Sub-tasks") |
|||
|
|||
def action_open_task(self): |
|||
return { |
|||
'view_mode': 'form', |
|||
'res_model': 'project.task.custom', |
|||
'res_id': self.id, |
|||
'type': 'ir.actions.act_window', |
|||
'context': self._context |
|||
} |
|||
|
|||
|
|||
class ProjectTaskTemplate(models.Model): |
|||
_name = 'project.task.template' |
|||
|
|||
name = fields.Char("Template name", translate=True) |
|||
task_ids = fields.One2many('project.task.custom', 'project_template_id', string="Tasks") |
@ -0,0 +1,104 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class ProjectProject(models.Model): |
|||
""" This class extends the 'project.project' model to add a many2one |
|||
field for selecting project task template. |
|||
Methods: |
|||
action_create_project_from_template(): |
|||
Creates a new project based on the selected project template. |
|||
_create_task(item, parent): |
|||
Creates a new project task for the given item and attaches |
|||
it to the current project. |
|||
""" |
|||
_inherit = 'project.project' |
|||
|
|||
project_template_id = fields.Many2one( |
|||
'project.task.template', |
|||
string='Project Template', |
|||
help='Select a project task template to use for this project.') |
|||
|
|||
def action_create_project_from_template(self): |
|||
""" Creates a new project based on the selected project template. |
|||
Returns: |
|||
dict: Action configuration to open the project form. |
|||
""" |
|||
if not self.project_template_id.stage_ids: |
|||
for item in self.project_template_id.task_ids: |
|||
self._create_task(item, False) |
|||
return { |
|||
'view_mode': 'form', |
|||
'res_model': 'project.project', |
|||
'res_id': self.id, |
|||
'type': 'ir.actions.act_window', |
|||
'context': self._context |
|||
} |
|||
else: |
|||
for item in self.project_template_id.stage_ids: |
|||
if self.id not in item.project_stage_id.project_ids.ids: |
|||
item.project_stage_id.project_ids = [(4, self.id)] |
|||
for task in item.task_ids: |
|||
self._create_task_with_stage(task, item.project_stage_id, |
|||
False) |
|||
|
|||
def _create_task(self, item, parent): |
|||
"""Creates a new project task for the given item and attaches it to |
|||
the current project. |
|||
Args: |
|||
item (models.Model): project task |
|||
parent (int): id of parent project task |
|||
""" |
|||
|
|||
task = self.env['project.task'].sudo().create({ |
|||
'project_id': self.id, |
|||
'name': item.name, |
|||
'parent_id': parent, |
|||
'stage_id': self.env['project.task.type'].search( |
|||
[('sequence', '=', 1)], limit=1).id, |
|||
'user_ids': item.user_ids, |
|||
'description': item.description, |
|||
'kanban_state': item.state or 'normal', |
|||
}) |
|||
for sub_task in item.child_ids: |
|||
self._create_task(sub_task, task.id) |
|||
|
|||
def _create_task_with_stage(self, item, stage, parent=False): |
|||
"""Creates a new project task with stage for the given item and attaches it to |
|||
the current project. |
|||
Args: |
|||
item (models.Model): project task |
|||
parent (int): id of parent project task |
|||
""" |
|||
|
|||
task = self.env['project.task'].sudo().create({ |
|||
'project_id': self.id, |
|||
'name': item.name, |
|||
'parent_id': parent, |
|||
'stage_id': stage.id, |
|||
'user_ids': item.user_ids, |
|||
'description': item.description, |
|||
'kanban_state': item.state or 'normal', |
|||
}) |
|||
for sub_task in item.child_ids: |
|||
self._create_task_with_stage(sub_task, stage, task.id) |
@ -0,0 +1,85 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class ProjectTaskCustom(models.Model): |
|||
"""Customized version of the 'project.task' model to support templates |
|||
and sub-tasks |
|||
Methods: |
|||
action_open_task(): |
|||
Returns an action to open the current task in a form view""" |
|||
_name = 'project.task.custom' |
|||
_description = 'Project Task Custom' |
|||
|
|||
name = fields.Char(string='Name', required=True, |
|||
help='Enter the name of the task') |
|||
project_template_id = fields.Many2one( |
|||
'project.task.template', string='Project Template', |
|||
help='Select a project task template to use for this task.') |
|||
description = fields.Html(string='Task Description', |
|||
help='Enter a description for the task.') |
|||
user_ids = fields.Many2many( |
|||
'res.users', relation='project_task_custom_user_rel', column1='task_id', |
|||
column2='user_id', string='Assignees', tracking=True, |
|||
help='Select the users who are assigned to this task.') |
|||
parent_id = fields.Many2one( |
|||
'project.task.custom', string='Parent Task', index=True, |
|||
help='Select the parent task, if any.') |
|||
child_ids = fields.One2many( |
|||
'project.task.custom', 'parent_id', string='Sub-Tasks', |
|||
help='List of sub-tasks, if any.') |
|||
show_tasks_page = fields.Boolean( |
|||
compute='_compute_show_tasks_page', |
|||
string="Show Tasks Page", |
|||
readonly=False) |
|||
|
|||
state = fields.Selection([ |
|||
('normal', 'In Progress'), |
|||
('done', 'Ready'), |
|||
('blocked', 'Blocked')], string='State', |
|||
default='normal', required=True) |
|||
|
|||
def action_open_task(self): |
|||
""" Action method to open the current task in a form view. |
|||
Returns: |
|||
dict: Action configuration to open the task form. |
|||
""" |
|||
return { |
|||
'view_mode': 'form', |
|||
'res_model': 'project.task.custom', |
|||
'res_id': self.id, |
|||
'type': 'ir.actions.act_window', |
|||
'context': self._context |
|||
} |
|||
|
|||
def _compute_show_tasks_page(self): |
|||
""" Compute function to determine whether Sub-Tasks are enabled. |
|||
This method computes the value of the 'show_tasks_page' field for each |
|||
record based on whether Sub-Tasks are enabled or not. If Sub-Tasks |
|||
are enabled, 'show_tasks_page' is set to True, allowing the display |
|||
of Sub-Tasks. If Sub-Tasks are not enabled, 'show_tasks_page' is set |
|||
to False. |
|||
""" |
|||
for task in self: |
|||
task.show_tasks_page = self.env.user.has_group( |
|||
'project.group_subtask_project') |
@ -0,0 +1,64 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models , api |
|||
|
|||
|
|||
class ProjectTaskTemplate(models.Model): |
|||
"""A model to define task templates for projects.""" |
|||
_name = 'project.task.template' |
|||
_description = 'Project Task Template' |
|||
|
|||
name = fields.Char(string='Template Name', translate=True, |
|||
help='Name for the task template.') |
|||
task_ids = fields.One2many( |
|||
'project.task.custom', 'project_template_id', |
|||
string='Tasks', |
|||
help='List of the tasks associated with this template.') |
|||
stage_ids = fields.One2many( |
|||
'project.stage', 'project_template_id', |
|||
string='Stages', |
|||
help='List of the stages associated with this template.') |
|||
|
|||
|
|||
class ProjectStage(models.Model): |
|||
"""A model to define task templates for projects.""" |
|||
_name = 'project.stage' |
|||
_order = "sequence,id" |
|||
|
|||
project_template_id = fields.Many2one( |
|||
'project.task.template', string='Project Template', |
|||
help='Select a project task template to use for this task.') |
|||
project_stage_id = fields.Many2one( |
|||
'project.task.type', string='Project Stage', |
|||
help='Select a project stage. ',required=True) |
|||
task_ids = fields.Many2many( |
|||
'project.task.custom', |
|||
help='Choose the tasks corresponding to each stage') |
|||
|
|||
sequence = fields.Integer(related="project_stage_id.sequence",readonly=False) |
|||
|
|||
|
|||
class ProjectTaskType(models.Model): |
|||
_inherit = "project.task.type" |
|||
|
|||
project_template_id = fields.Many2one( |
|||
'project.task.template') |
|
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 54 KiB |
@ -0,0 +1,33 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<odoo> |
|||
<!-- Inherits simplified project.project form view to add fields --> |
|||
<record id="project_project_view_form_simplified" model="ir.ui.view" > |
|||
<field name="name">project.project.view.form.inherit.project.tasks.from.templates</field> |
|||
<field name="model">project.project</field> |
|||
<field name="inherit_id" ref="project.project_project_view_form_simplified"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='name']" position="after"> |
|||
<field name="project_template_id" string="Template"/> |
|||
</xpath> |
|||
<xpath expr="//group" position="after"> |
|||
<footer> |
|||
<button string="Create" name="action_view_tasks" type="object" class="btn-primary o_open_tasks" |
|||
data-hotkey="q"/> |
|||
<button string="Discard" class="btn-secondary" special="cancel" data-hotkey="z"/> |
|||
</footer> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
<!-- Inherits simplified project.project.footer form view to add buttons --> |
|||
<record id="project.project_project_view_form_simplified_footer" model="ir.ui.view" > |
|||
<field name="name">project.project.view.form.simplified</field> |
|||
<field name="model">project.project</field> |
|||
<field name="inherit_id" ref="project.project_project_view_form_simplified"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//button[hasclass('o_open_tasks')]" position="after"> |
|||
<button string="Create Project from Template" name="action_create_project_from_template" |
|||
type="object" class="btn-primary o_open_tasks" attrs="{'invisible':[('project_template_id','=',False)]}"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -1,97 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<odoo> |
|||
|
|||
<record id="create_project_templates" model="ir.actions.act_window"> |
|||
<field name="name">Project Templates</field> |
|||
<field name="res_model">project.task.template</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem id="project_menu_templates" |
|||
action="create_project_templates" |
|||
parent="project.menu_project_config"/> |
|||
|
|||
<record model="ir.ui.view" id="project_tasks_from_templates"> |
|||
<field name="name">project.template.tasks.manager</field> |
|||
<field name="model">project.task.template</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<field name="name"/> |
|||
</group> |
|||
<notebook> |
|||
<page name="tasks_page" string="Tasks"> |
|||
<field name="task_ids"> |
|||
<tree editable="bottom"> |
|||
<field name="name"/> |
|||
<field name="description" widget="html"/> |
|||
<field name="user_ids" widget="many2many_avatar_user" optional="show" |
|||
domain="[('share', '=', False), ('active', '=', True)]"/> |
|||
<button name="action_open_task" type="object" title="View Task" |
|||
string="View Task" class="btn btn-link pull-right"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
|
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="project_tasks_custom_form"> |
|||
<field name="name">project.custom.tasks.manager</field> |
|||
<field name="model">project.task.custom</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<field name="name"/> |
|||
<field name="description" widget="html" options="{'collaborative': true}"/> |
|||
</group> |
|||
<notebook> |
|||
<page name="tasks_page" string="Tasks"> |
|||
<tree editable="bottom"> |
|||
<field name="child_ids"/> |
|||
</tree> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
|
|||
</field> |
|||
</record> |
|||
|
|||
<record id="project.project_project_view_form_simplified_footer" model="ir.ui.view"> |
|||
<field name="name">project.project.view.form.simplified</field> |
|||
<field name="model">project.project</field> |
|||
<field name="inherit_id" ref="project.project_project_view_form_simplified"/> |
|||
<field name="mode">primary</field> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='name']" position="after"> |
|||
<field name="project_template_id" string="Template"/> |
|||
</xpath> |
|||
<xpath expr="//group" position="after"> |
|||
<footer> |
|||
<button string="Create Project from Template" name="action_create_project_from_template" |
|||
type="object" class="btn-primary o_open_tasks" data-hotkey="l"/> |
|||
<button string="Create" name="action_view_tasks" type="object" class="btn-primary o_open_tasks" |
|||
data-hotkey="q"/> |
|||
<button string="Discard" class="btn-secondary" special="cancel" data-hotkey="z"/> |
|||
</footer> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="project_tasks_from_templates_tree"> |
|||
<field name="name">project.template.tasks.manager.tree</field> |
|||
<field name="model">project.task.template</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Form view for project.task.custom --> |
|||
<record id="project_task_custom_view_form" model="ir.ui.view"> |
|||
<field name="name">project.task.custom.view.form</field> |
|||
<field name="model">project.task.custom</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<field name="name"/> |
|||
<field name="description" widget="html"/> |
|||
<field name="show_tasks_page" invisible="1"/> |
|||
</group> |
|||
<notebook> |
|||
<page name="tasks_page" string="Tasks" attrs="{'invisible': [('show_tasks_page', '=', False)]}"> |
|||
<field name="child_ids"> |
|||
<tree editable="bottom"> |
|||
<field name="name"/> |
|||
<field name="state"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,62 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Tree view for project.task.template --> |
|||
<record id="project_task_template_view_tree" model="ir.ui.view"> |
|||
<field name="name">project.task.template.view.tree</field> |
|||
<field name="model">project.task.template</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<!-- Form view for project.task.template --> |
|||
<record id="project_task_template_view_form" model="ir.ui.view"> |
|||
<field name="name">project.task.template.view.form</field> |
|||
<field name="model">project.task.template</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<field name="name"/> |
|||
</group> |
|||
<notebook> |
|||
<page name="tasks_page" string="Tasks"> |
|||
<field name="task_ids"> |
|||
<tree editable="bottom"> |
|||
<field name="name"/> |
|||
<field name="description" type="html"/> |
|||
<field name="user_ids" widget="many2many_avatar_user" |
|||
optional="show" domain="[('share', '=', False), ('active', '=', True)]"/> |
|||
<field name="state"/> |
|||
<button name="action_open_task" type="object" title="View Task" |
|||
string="View Task" class="btn btn-link pull-right"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page name="stages_page" string="Stages"> |
|||
<field name="stage_ids"> |
|||
<tree editable="bottom" > |
|||
<field name='sequence' widget='handle'/> |
|||
<field name="project_stage_id" domain="[('project_template_id', '=', project_template_id)]" context="{'default_project_template_id': project_template_id, 'default_sequence': sequence}" options="{'no_create_edit':True}"/> |
|||
<field name="project_template_id" invisible="1"/> |
|||
<field name="task_ids" domain="[('project_template_id', '=', project_template_id)]" widget="many2many_tags"/> |
|||
</tree> |
|||
|
|||
</field> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<!-- Action window for project.task.template --> |
|||
<record id="project_task_template_action" model="ir.actions.act_window"> |
|||
<field name="name">Project Templates</field> |
|||
<field name="res_model">project.task.template</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
<!-- Menu --> |
|||
<menuitem id="project_task_template_menu_action" action="project_task_template_action" |
|||
parent="project.menu_project_config"/> |
|||
</odoo> |