Files
odoo_source/addons/project/tests/test_project_recurrence.py
T
Victor Piryns (pivi) ebfcdc95d2 [FIX] project: disable recurrence for all tasks linked to a recurrence
Current behaviour:
If you disable the recurrence for 1 task in a suite of recurrence,
if you had other tasks belonging to the same recurrence suite, they
would still be with recurrence activated.

Expected behaviour:
It doesn't make sense for some of the tasks in a suite of tasks in a
recurrence to enabled and others disabled. If we disable the
recurrence on 1 such tasks, all tasks should linked to that
recurrence should be set as non-recurrent, regardless if the
edit-mode is set on "This task".

Steps to reproduce:
- For 14.0 -> saas-16.1:
  - Install Project, Studio
  - Turn on in Settings the "Recurrent Tasks"
  - Create a new project and a task in it
  - With studio, in debug mode, add a related field to the task form
    that relates to `next_recurrence_date`. Make sure it's not "read
    only"
  - On the task, turn on the recurrence, set the frequency to each
    day, set the `next_recurrence_date` as a day in the past
  - Run the Scheduled Action "Project : Create Recurring Tasks"
  - On one of the task, disable the recurrence
  - Go to the other task, see that their recurrence is still active,
    and the frequency changed to the defaults values of once a week.
- For saas-16.2 -> master:
  - Install Project
  - Turn on in Settings the "Recurrent Tasks"
  - Create a new project and a task in it
  - Activate the recurrence on the task, set a planned date in the past
  - Set the task as "Done", this should create an new instance of the
    recurrence.
  - Disable the recurrence option in one of the task, observe that
    is doesn't change for the other task, and the recurrence
    frequency is reset to default values.

Reason for the problem:
When disabling the recurrence on 1 task, with the edit-mode set as
"This task", the recurrence is being deleted, but we don't disable
the recurrence of the other tasks linked to that recurrence.

Fix:
When we are writing `False` on `recurring_task` on a task, we
explicitely write `False` on `recurring_task` on all tasks that belong
to the recurrence after the deletion of the recurrence itself.

Affected versions:
- 14.0
- 15.0
- saas-15.2
- 16.0
- saas-16.1
- saas-16.2
- saas-16.3
- master

opw-3265212

closes odoo/odoo#128703

X-original-commit: 0a83f4030b07aba25b054aa453d81c0e27b98cc8
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
2023-07-17 16:45:59 +02:00

149 lines
6.1 KiB
Python

# -*- coding: utf-8 -*-
from odoo import fields
from odoo.tests.common import Form, TransactionCase
from datetime import datetime, time
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
class TestProjectRecurrence(TransactionCase):
@classmethod
def setUpClass(cls):
super(TestProjectRecurrence, cls).setUpClass()
cls.env.user.groups_id += cls.env.ref('project.group_project_recurring_tasks')
cls.stage_a = cls.env['project.task.type'].create({'name': 'a'})
cls.stage_b = cls.env['project.task.type'].create({'name': 'b'})
cls.project_recurring = cls.env['project.project'].with_context({'mail_create_nolog': True}).create({
'name': 'Recurring',
'type_ids': [
(4, cls.stage_a.id),
(4, cls.stage_b.id),
]
})
cls.classPatch(cls.env.cr, 'now', fields.Datetime.now)
cls.date_01_01 = datetime.combine(datetime.now() + relativedelta(years=-1, month=1, day=1), time(0, 0))
def test_recurrence_simple(self):
with freeze_time(self.date_01_01):
form = Form(self.env['project.task'])
form.name = 'test recurring task'
form.project_id = self.project_recurring
form.recurring_task = True
form.repeat_interval = 5
form.repeat_unit = 'month'
form.repeat_type = 'forever'
task = form.save()
self.assertTrue(bool(task.recurrence_id), 'should create a recurrence')
task.write(dict(repeat_interval=2))
self.assertEqual(task.recurrence_id.repeat_interval, 2, 'recurrence should be updated')
task.recurring_task = False
self.assertFalse(bool(task.recurrence_id), 'the recurrence should be deleted')
def test_recurrent_tasks_fields(self):
self.env['project.tags'].create({
'name': 'Test Tag',
})
with freeze_time(self.date_01_01):
form = Form(self.env['project.task'])
form.project_id = self.project_recurring
form.name = 'name'
form.description = 'description'
form.priority = '1'
form.stage_id = self.stage_b
form.tag_ids.add(self.env['project.tags'].search([], limit=1))
form.date_deadline = self.date_01_01 + relativedelta(weeks=1)
form.recurring_task = True
form.repeat_interval = 2
form.repeat_unit = 'month'
form.repeat_type = 'forever'
task = form.save()
with freeze_time(self.date_01_01 + relativedelta(months=1)):
task.state = '1_done'
other_task = task.recurrence_id.task_ids - task
self.assertEqual(
other_task.date_deadline, task.date_deadline + relativedelta(months=2),
"Next occurrence should have previous deadline + interval * unit",
)
for copied_field in ['project_id', 'name', 'description', 'tag_ids']:
self.assertEqual(other_task[copied_field], task[copied_field], f"Next occurrence's {copied_field} should have been copied")
for reset_field in ['priority', 'stage_id', 'state']:
self.assertNotEqual(other_task[reset_field], task[reset_field], f"Next occurrence's {reset_field} should have been reset")
def test_recurrence_until(self):
with freeze_time(self.date_01_01):
form = Form(self.env['project.task'])
form.name = 'test recurring task'
form.project_id = self.project_recurring
form.recurring_task = True
form.repeat_interval = 5
form.repeat_unit = 'month'
form.repeat_type = 'until'
form.repeat_until = self.date_01_01 + relativedelta(months=1)
task = form.save()
with freeze_time(self.date_01_01 + relativedelta(days=30)):
task.state = '1_done'
self.assertEqual(len(task.recurrence_id.task_ids), 2, "Since this is before repeat_until, next occurrence should have been created")
with freeze_time(self.date_01_01 + relativedelta(days=32)):
task.state = '1_done'
self.assertEqual(len(task.recurrence_id.task_ids), 2, "Since this is after repeat_until, next occurrence shouldn't have been created")
def test_recurring_settings_change(self):
self.env['res.config.settings'] \
.create({'group_project_recurring_tasks': True}) \
.execute()
test_task = self.env['project.task'].create({
'name': "Recurring Task",
'project_id': self.project_recurring.id,
'recurring_task': True,
})
self.assertTrue(test_task.recurring_task, 'The "Recurring" feature should be enabled from settings.')
self.env['res.config.settings'] \
.create({'group_project_recurring_tasks': False}) \
.execute()
self.assertFalse(test_task.recurring_task, 'The "Recurring" feature should not be enabled by default.')
def test_disabling_recurrence(self):
"""
Disabling the recurrence of one task in a recurrence suite should disable *all*
recurrences option on the tasks linked to that recurrence
"""
with freeze_time(self.date_01_01):
form = Form(self.env['project.task'])
form.name = 'test recurring task'
form.project_id = self.project_recurring
form.recurring_task = True
form.repeat_interval = 5
form.repeat_unit = 'day'
form.repeat_type = 'forever'
task = form.save()
with freeze_time(self.date_01_01 + relativedelta(day=1)):
task.state = '1_done'
other_task = self.project_recurring.task_ids - task
with freeze_time(self.date_01_01 + relativedelta(day=2)):
other_task.state = '1_done'
task_c, task_b, task_a = self.env['project.task'].search([('project_id', '=', self.project_recurring.id)])
task_b.recurring_task = False
self.assertFalse(any((task_a + task_b + task_c).mapped('recurring_task')),
"All tasks in the recurrence should have their recurrence disabled")