[IMP] project: check no cyclic task dependencies

Before this commit, if we have for instance 3 tasks called A, B and C
where A depends on B and B depends on A then we have a cyclic dependency.
Another example with the same tasks, we can have a cyclic dependency if
A depends on B, B depends on C and C depends on A.

This commit checks we have no cyclic dependencies when the user adds a
dependency on a task.

task-2387984

closes #66740
This commit is contained in:
Xavier BOL (xbo)
2021-03-12 14:15:36 +01:00
parent 1c691c26a8
commit 63777d3c3f
2 changed files with 50 additions and 0 deletions
+5
View File
@@ -737,6 +737,11 @@ class Task(models.Model):
repeat_show_week = fields.Boolean(compute='_compute_repeat_visibility')
repeat_show_month = fields.Boolean(compute='_compute_repeat_visibility')
@api.constrains('depend_on_ids')
def _check_no_cyclic_dependencies(self):
if not self._check_m2m_recursion('depend_on_ids'):
raise ValidationError(_("You cannot create cyclic dependency."))
@api.model
def _get_recurrence_fields(self):
return ['repeat_interval', 'repeat_unit', 'repeat_type', 'repeat_until', 'repeat_number',
@@ -40,3 +40,48 @@ class TestTaskDependencies(TestProjectCommon):
'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.")
def test_cyclic_dependencies(self):
""" Test the cyclic dependencies
Test Case:
=========
1) Check initial setting on three tasks
2) Add task2 as dependency in task1
3) Add task3 as dependency in task2
4) Add task1 as dependency in task3 and check a validation error is raised
5) Add task1 as dependency in task2 and check a validation error is raised
"""
# 1) Check initial setting on three tasks
self.assertTrue(
len(self.task_1.depend_on_ids) == len(self.task_2.depend_on_ids) == len(self.task_3.depend_on_ids) == 0,
"The three tasks should depend on no tasks.")
self.assertTrue(self.task_1.allow_task_dependencies, 'The task dependencies feature should be enable.')
self.assertTrue(self.task_2.allow_task_dependencies, 'The task dependencies feature should be enable.')
self.assertTrue(self.task_3.allow_task_dependencies, 'The task dependencies feature should be enable.')
# 2) Add task2 as dependency in task1
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 one dependency.')
# 3) Add task3 as dependency in task2
self.task_2.write({
'depend_on_ids': [Command.link(self.task_3.id)],
})
self.assertEqual(len(self.task_2.depend_on_ids), 1, "The task 2 should have one dependency.")
# 4) Add task1 as dependency in task3 and check a validation error is raised
with self.assertRaises(ValidationError), self.cr.savepoint():
self.task_3.write({
'depend_on_ids': [Command.link(self.task_1.id)],
})
self.assertEqual(len(self.task_3.depend_on_ids), 0, "The dependency should not be added in the task 3 because of a cyclic dependency.")
# 5) Add task1 as dependency in task2 and check a validation error is raised
with self.assertRaises(ValidationError), self.cr.savepoint():
self.task_2.write({
'depend_on_ids': [Command.link(self.task_1.id)],
})
self.assertEqual(len(self.task_2.depend_on_ids), 1, "The number of dependencies should no change in the task 2 because of a cyclic dependency.")