[FIX] project: fix infinite recurring tasks creation
For recurrences of repeat_type = 'after', the daily cron would create tasks infinitely. * The cron creates recurring task for all recurrences for which next_recurrence_date < today. * next_recurrence_date was never updated. This commit ensures that next_recurrence_date is set to False for repeat_type = 'after' recurrences, when the last recurrence is created. X-original-commit: e7be857bea964628b80d4d3c1314dc231e0da947
This commit is contained in:
@@ -226,10 +226,19 @@ class ProjectTaskRecurrence(models.Model):
|
||||
def _set_next_recurrence_date(self):
|
||||
today = fields.Date.today()
|
||||
tomorrow = today + relativedelta(days=1)
|
||||
for recurrence in self.filtered(lambda r: r.repeat_type == 'after' and r.recurrence_left > 0 or r.repeat_type == 'until' and r.repeat_until >= today or r.repeat_type == 'forever'):
|
||||
next_date = self._get_next_recurring_dates(tomorrow, recurrence.repeat_interval, recurrence.repeat_unit, recurrence.repeat_type, recurrence.repeat_until, recurrence.repeat_on_month, recurrence.repeat_on_year, recurrence._get_weekdays(), recurrence.repeat_day, recurrence.repeat_week, recurrence.repeat_month, count=1)
|
||||
recurrence.next_recurrence_date = next_date[0] if next_date else False
|
||||
for recurrence in self.filtered(
|
||||
lambda r:
|
||||
r.repeat_type == 'after' and r.recurrence_left >= 0
|
||||
or r.repeat_type == 'until' and r.repeat_until >= today
|
||||
or r.repeat_type == 'forever'
|
||||
):
|
||||
if recurrence.repeat_type == 'after' and recurrence.recurrence_left == 0:
|
||||
recurrence.next_recurrence_date = False
|
||||
else:
|
||||
next_date = self._get_next_recurring_dates(tomorrow, recurrence.repeat_interval, recurrence.repeat_unit, recurrence.repeat_type, recurrence.repeat_until, recurrence.repeat_on_month, recurrence.repeat_on_year, recurrence._get_weekdays(), recurrence.repeat_day, recurrence.repeat_week, recurrence.repeat_month, count=1)
|
||||
recurrence.next_recurrence_date = next_date[0] if next_date else False
|
||||
|
||||
@api.model
|
||||
def _cron_create_recurring_tasks(self):
|
||||
if not self.env.user.has_group('project.group_project_recurring_tasks'):
|
||||
return
|
||||
|
||||
@@ -7,8 +7,8 @@ from odoo import fields
|
||||
|
||||
from datetime import date, datetime
|
||||
from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
|
||||
from freezegun import freeze_time
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
class TestProjectrecurrence(TransactionCase):
|
||||
@classmethod
|
||||
@@ -32,7 +32,7 @@ class TestProjectrecurrence(TransactionCase):
|
||||
self.env.cr.execute("UPDATE project_task SET create_date=%s WHERE id=%s", (create_date, task_id))
|
||||
|
||||
def test_recurrence_simple(self):
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 2, 1)):
|
||||
with freeze_time("2020-02-01"):
|
||||
with Form(self.env['project.task']) as form:
|
||||
form.name = 'test recurring task'
|
||||
form.project_id = self.project_recurring
|
||||
@@ -57,7 +57,8 @@ class TestProjectrecurrence(TransactionCase):
|
||||
self.assertFalse(bool(task.recurrence_id), 'the recurrence should be deleted')
|
||||
|
||||
def test_recurrence_cron(self):
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 1, 1)):
|
||||
domain = [('project_id', '=', self.project_recurring.id)]
|
||||
with freeze_time("2020-01-01"):
|
||||
form = Form(self.env['project.task'])
|
||||
form.name = 'test recurring task'
|
||||
form.description = 'my super recurring task bla bla bla'
|
||||
@@ -75,22 +76,27 @@ class TestProjectrecurrence(TransactionCase):
|
||||
task.planned_hours = 2
|
||||
|
||||
self.assertEqual(task.recurrence_id.next_recurrence_date, date(2020, 1, 15))
|
||||
self.assertEqual(self.env['project.task'].search_count([('project_id', '=', self.project_recurring.id)]), 1)
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 1)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
self.assertEqual(self.env['project.task'].search_count([('project_id', '=', self.project_recurring.id)]), 1, 'no extra task should be created')
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 1, 'no extra task should be created')
|
||||
self.assertEqual(task.recurrence_id.recurrence_left, 2)
|
||||
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 1, 15)):
|
||||
self.assertEqual(self.env['project.task'].search_count([('project_id', '=', self.project_recurring.id)]), 1)
|
||||
with freeze_time("2020-01-15"):
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 1)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
self.assertEqual(self.env['project.task'].search_count([('project_id', '=', self.project_recurring.id)]), 2)
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 2)
|
||||
self.assertEqual(task.recurrence_id.recurrence_left, 1)
|
||||
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 2, 15)):
|
||||
with freeze_time("2020-02-15"):
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 3)
|
||||
self.assertEqual(task.recurrence_id.recurrence_left, 0)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 3)
|
||||
self.assertEqual(task.recurrence_id.recurrence_left, 0)
|
||||
|
||||
tasks = self.env['project.task'].search([('project_id', '=', self.project_recurring.id)])
|
||||
|
||||
tasks = self.env['project.task'].search(domain)
|
||||
self.assertEqual(len(tasks), 3)
|
||||
|
||||
self.assertTrue(bool(tasks[2].date_deadline))
|
||||
@@ -100,7 +106,7 @@ class TestProjectrecurrence(TransactionCase):
|
||||
self.assertTrue(tasks[0][f] == tasks[1][f] == tasks[2][f], "Field %s should have been copied" % f)
|
||||
|
||||
def test_recurrence_update_task(self):
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 1, 1)):
|
||||
with freeze_time("2020-01-01"):
|
||||
task = self.env['project.task'].create({
|
||||
'name': 'test recurring task',
|
||||
'project_id': self.project_recurring.id,
|
||||
@@ -112,10 +118,10 @@ class TestProjectrecurrence(TransactionCase):
|
||||
'mon': True,
|
||||
})
|
||||
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 1, 6)):
|
||||
with freeze_time("2020-01-06"):
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
|
||||
with patch.object(fields.Date, 'today', lambda: datetime(2020, 1, 13)):
|
||||
with freeze_time("2020-01-13"):
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
|
||||
task_c, task_b, task_a = self.env['project.task'].search([('project_id', '=', self.project_recurring.id)])
|
||||
|
||||
Reference in New Issue
Block a user