162 lines
5.1 KiB
Python
162 lines
5.1 KiB
Python
from odoo import models, fields, api, _
|
|
|
|
|
|
class ProjectTaskTemplate(models.Model):
|
|
_name = "project.task.template"
|
|
_description = "Template for new project tasks"
|
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
|
_order = "sequence, id"
|
|
|
|
@api.model
|
|
def _current_company(self):
|
|
return self.env.company
|
|
|
|
name = fields.Char(
|
|
string="Task Title",
|
|
required=True,
|
|
tracking=True,
|
|
)
|
|
|
|
description = fields.Html(tracking=True)
|
|
|
|
assignee_ids = fields.Many2many(
|
|
comodel_name="res.users",
|
|
string="Default Assignees",
|
|
help="Employees assigned to tasks created from this template.",
|
|
tracking=1,
|
|
)
|
|
|
|
project_id = fields.Many2one(
|
|
comodel_name="project.project",
|
|
string="Default Project",
|
|
help="Default project for tasks created from this template.",
|
|
tracking=2,
|
|
)
|
|
|
|
tag_ids = fields.Many2many(
|
|
comodel_name="project.tags",
|
|
string="Default Tags",
|
|
help="Default tags for tasks created from this template.",
|
|
tracking=3,
|
|
)
|
|
|
|
parent_id = fields.Many2one(
|
|
comodel_name="project.task.template",
|
|
string="Parent Task Template",
|
|
ondelete="cascade",
|
|
tracking=4,
|
|
)
|
|
|
|
subtask_ids = fields.One2many(
|
|
comodel_name="project.task.template",
|
|
inverse_name="parent_id",
|
|
string="Subtask Templates",
|
|
copy=True,
|
|
)
|
|
|
|
sequence = fields.Integer(default=10)
|
|
|
|
company_id = fields.Many2one(
|
|
comodel_name="res.company",
|
|
string="Company",
|
|
index=True,
|
|
default=_current_company,
|
|
tracking=5,
|
|
)
|
|
|
|
allocated_hours = fields.Float(
|
|
"Initially Allocated Hours",
|
|
tracking=6,
|
|
)
|
|
|
|
active = fields.Boolean(
|
|
default=True,
|
|
tracking=7,
|
|
)
|
|
|
|
task_count = fields.Integer(
|
|
string="Tasks",
|
|
compute="_compute_task_count",
|
|
)
|
|
|
|
def _compute_task_count(self):
|
|
for template in self:
|
|
template.task_count = self.env["project.task"].search_count(
|
|
[("template_id", "=", template.id)]
|
|
)
|
|
|
|
def action_view_tasks(self):
|
|
"""Open the tree view of tasks created from this template."""
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_task")
|
|
action["domain"] = [("template_id", "=", self.id)]
|
|
action["context"] = {
|
|
"default_template_id": self.id,
|
|
"create": False, # Don't allow creation from this view
|
|
}
|
|
return action
|
|
|
|
def action_open_task(self):
|
|
return {
|
|
"view_mode": "form",
|
|
"res_model": "project.task.template",
|
|
"res_id": self.id,
|
|
"type": "ir.actions.act_window",
|
|
"context": self._context,
|
|
}
|
|
|
|
def _prepare_new_task_values_from_self(self, project, name=False, parent_id=False):
|
|
"""Prepare values for creating a new task from this template.
|
|
|
|
:param project: project.project record the task should be added to
|
|
:param name: name for the new task (defaults to template name)
|
|
:param parent_id: parent task for the new task (none by default)
|
|
:return: dict of values for creating the task
|
|
"""
|
|
vals = {
|
|
"project_id": project.id,
|
|
"name": name or self.name,
|
|
"description": self.description,
|
|
"parent_id": parent_id,
|
|
"user_ids": self.assignee_ids.ids,
|
|
"tag_ids": self.tag_ids.ids,
|
|
"allocated_hours": self.allocated_hours,
|
|
"sequence": self.sequence,
|
|
"company_id": self.company_id.id,
|
|
"template_id": self.id,
|
|
}
|
|
return vals
|
|
|
|
def create_task_from_self(self, project, name=False, parent_id=False):
|
|
"""Create a project.task from this template and return it.
|
|
Can be called on a RecordSet of multiple templates.
|
|
|
|
:param project: project.project record the task should be added to
|
|
:param name: name for the new task (defaults to template name)
|
|
:param parent_id: parent task for the new task (none by default)
|
|
:return: project.task record created from this template
|
|
"""
|
|
tasks = self.env["project.task"]
|
|
for rec in self:
|
|
vals = rec._prepare_new_task_values_from_self(project, name, parent_id)
|
|
task = rec.env["project.task"].create(vals)
|
|
rec.subtask_ids.create_task_from_self(project, name=False, parent_id=task.id)
|
|
tasks |= task
|
|
return tasks
|
|
|
|
def copy(self, default=None):
|
|
"""Support copying templates, ensuring proper duplication of the task hierarchy."""
|
|
self.ensure_one()
|
|
if default is None:
|
|
default = {}
|
|
if "name" not in default:
|
|
default["name"] = self.name + _(" (copy)")
|
|
# Don't copy parent reference, this will be handled by recursion
|
|
default["parent_id"] = False
|
|
new = super().copy(default)
|
|
|
|
# Copy subtasks, linking them to the new template
|
|
for subtask in self.subtask_ids:
|
|
subtask.copy({"parent_id": new.id})
|
|
|
|
return new
|