diff --git a/addons/hr_timesheet/views/project_views.xml b/addons/hr_timesheet/views/project_views.xml
index 9d2fc6a4845..a54f429a15c 100644
--- a/addons/hr_timesheet/views/project_views.xml
+++ b/addons/hr_timesheet/views/project_views.xml
@@ -196,6 +196,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index ff2bb37a754..66ccaabbf23 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -650,6 +650,10 @@ class Task(models.Model):
# customer portal: include comment and incoming emails in communication history
website_message_ids = fields.One2many(domain=lambda self: [('model', '=', self._name), ('message_type', 'in', ['email', 'comment'])])
+ # Task Dependencies fields
+ allow_task_dependencies = fields.Boolean(related='project_id.allow_task_dependencies')
+ depend_on_ids = fields.Many2many('project.task', relation="task_dependencies_rel", column1="task_id", column2="depends_on_id", string="Blocked By")
+
# recurrence fields
allow_recurring_tasks = fields.Boolean(related='project_id.allow_recurring_tasks')
recurring_task = fields.Boolean(string="Recurrent")
@@ -1172,7 +1176,7 @@ class Task(models.Model):
if task.project_id.partner_id:
task.partner_id = task.project_id.partner_id
else:
- task.partner_id = task.project_id.partner_id or task.parent_id.partner_id
+ task.partner_id = task.project_id.partner_id or task.parent_id.partner_id
@api.depends('partner_id.email', 'parent_id.email_from')
def _compute_email_from(self):
@@ -1393,6 +1397,16 @@ class Task(models.Model):
# Actions
# ------------
+ def action_open_task_form(self):
+ """ Opens the form view of the task """
+ return {
+ 'view_mode': 'form',
+ 'res_model': 'project.task',
+ 'res_id': self.id,
+ 'type': 'ir.actions.act_window',
+ 'context': dict(self._context, create=False)
+ }
+
def action_recurring_tasks(self):
return {
'name': 'Tasks in Recurrence',
diff --git a/addons/project/static/src/scss/project_form.scss b/addons/project/static/src/scss/project_form.scss
new file mode 100644
index 00000000000..b81797fde42
--- /dev/null
+++ b/addons/project/static/src/scss/project_form.scss
@@ -0,0 +1,3 @@
+.o_form_project_tasks div.o_field_many2many[name=depend_on_ids] tr.o_selected_row td.o_list_button {
+ background-color: $table-border-color !important;
+}
diff --git a/addons/project/tests/__init__.py b/addons/project/tests/__init__.py
index d5c89ac7b9d..0be5e1c075d 100644
--- a/addons/project/tests/__init__.py
+++ b/addons/project/tests/__init__.py
@@ -7,3 +7,4 @@ from . import test_project_flow
from . import test_project_recurrence
from . import test_project_ui
from . import test_multicompany
+from . import test_task_dependencies
diff --git a/addons/project/tests/test_task_dependencies.py b/addons/project/tests/test_task_dependencies.py
new file mode 100644
index 00000000000..5650780d3fc
--- /dev/null
+++ b/addons/project/tests/test_task_dependencies.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+from odoo.fields import Command
+from odoo.exceptions import ValidationError
+from odoo.tests import tagged
+
+from odoo.addons.project.tests.test_project_base import TestProjectCommon
+
+
+@tagged('-at_install', 'post_install', 'task_dependencies')
+class TestTaskDependencies(TestProjectCommon):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ cls.project_pigs.write({
+ 'allow_task_dependencies': True,
+ })
+ cls.task_3 = cls.env['project.task'].with_context({'mail_create_nolog': True}).create({
+ 'name': 'Pigs UserTask 2',
+ 'user_id': cls.user_projectuser.id,
+ 'project_id': cls.project_pigs.id,
+ })
+
+ def test_task_dependencies(self):
+ """ Test the task dependencies feature
+
+ Test Case:
+ =========
+ 1) Add task2 as dependency in task1
+ 2) Checks if the task1 has the task in depend_on_ids field.
+ """
+ self.assertEqual(len(self.task_1.depend_on_ids), 0, "The task 1 should not have any dependency.")
+ self.task_1.write({
+ 'depend_on_ids': [Command.link(self.task_2.id)],
+ })
+ self.assertEqual(len(self.task_1.depend_on_ids), 1, "The task 1 should have a dependency.")
+ self.task_1.write({
+ 'depend_on_ids': [Command.link(self.task_3.id)],
+ })
+ self.assertEqual(len(self.task_1.depend_on_ids), 2, "The task 1 should have two dependencies.")
diff --git a/addons/project/views/project_assets.xml b/addons/project/views/project_assets.xml
index 76c047170b5..fdec23a8dfd 100644
--- a/addons/project/views/project_assets.xml
+++ b/addons/project/views/project_assets.xml
@@ -11,6 +11,7 @@
+
diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml
index e91d50ddd45..97d81f72a88 100644
--- a/addons/project/views/project_views.xml
+++ b/addons/project/views/project_views.xml
@@ -658,6 +658,7 @@
+
@@ -799,6 +800,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+