[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:
@@ -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.")
|
||||
|
||||
Reference in New Issue
Block a user