[REV] project: re-allow recurring sub tasks
With the modification introducted in the PR #62577, create recurring subtask was no more allowed. This commits reverts this limitation and adds tests to verify this behaviour. PR : #77126 task-2522076 X-original-commit: f6b12588757bd7f2d7802264fc7cd1aaae4c6c57
This commit is contained in:
@@ -7,6 +7,11 @@
|
||||
<field name="groups_id" eval="[(4, ref('group_project_manager'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Groups : Add subtasks and recurring tasks by default -->
|
||||
<record id="base.group_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_subtask_project')), (4, ref('group_project_recurring_tasks'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Categories -->
|
||||
<record id="project_tags_00" model="project.tags">
|
||||
<field name="name">Bug</field>
|
||||
@@ -875,5 +880,94 @@ Send it ASAP, its urgent.</field>
|
||||
<field name="progress" eval="35"/>
|
||||
<field name="status">at_risk</field>
|
||||
</record>
|
||||
|
||||
<!-- Recurring tasks and subtasks -->
|
||||
<record id="project_task_recurrence_1" model="project.task.recurrence">
|
||||
<field name="recurrence_left">3</field>
|
||||
<field name="repeat_unit">month</field>
|
||||
<field name="repeat_on_month">date</field>
|
||||
<field name="repeat_type">after</field>
|
||||
<field name="repeat_number">4</field>
|
||||
<field name="repeat_day">1</field>
|
||||
<field name="repeat_weekday">mon</field>
|
||||
<field name="create_date" eval="DateTime.now() + relativedelta(weeks=-2)"/>
|
||||
</record>
|
||||
<record id="project_task_recurrence_1" model="project.task.recurrence">
|
||||
<field name="next_recurrence_date" eval="DateTime.now() + relativedelta(weeks=-2)"/>
|
||||
</record>
|
||||
<record id="project_task_recurrence_2" model="project.task.recurrence">
|
||||
<field name="recurrence_left">20</field>
|
||||
<field name="mon" eval="True"/>
|
||||
<field name="tue" eval="True"/>
|
||||
<field name="wed" eval="True"/>
|
||||
<field name="thu" eval="True"/>
|
||||
<field name="fri" eval="True"/>
|
||||
<field name="repeat_type">after</field>
|
||||
<field name="repeat_number">20</field>
|
||||
</record>
|
||||
<record id="project_task_recurrence_2" model="project.task.recurrence">
|
||||
<field name="next_recurrence_date" eval="DateTime.now() + relativedelta(weeks=-2)"/>
|
||||
</record>
|
||||
<record id="project_task_27" model="project.task">
|
||||
<field name="sequence">20</field>
|
||||
<field name="planned_hours">20.0</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="name">Customer review</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
<field name="recurring_task" eval="True"/>
|
||||
<field name="recurrence_id" ref="project_task_recurrence_1"/>
|
||||
<field name="create_date" eval="DateTime.now() + relativedelta(weeks=-2)"/>
|
||||
</record>
|
||||
<record id="project_task_28" model="project.task">
|
||||
<field name="sequence">20</field>
|
||||
<field name="planned_hours">0.25</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="parent_id" ref="project.project_task_27"/>
|
||||
<field name="name">Daily stand-up meeting - Send minutes</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
<field name="recurring_task" eval="True"/>
|
||||
<field name="recurrence_id" ref="project_task_recurrence_2"/>
|
||||
<field name="create_date" eval="DateTime.now() - relativedelta(weeks=-1)"/>
|
||||
</record>
|
||||
<record id="project_task_29" model="project.task">
|
||||
<field name="sequence">20</field>
|
||||
<field name="planned_hours">8.0</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="parent_id" ref="project.project_task_27"/>
|
||||
<field name="name">Customer Meeting</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
</record>
|
||||
<record id="project_task_30" model="project.task">
|
||||
<field name="sequence">10</field>
|
||||
<field name="planned_hours">2.0</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="parent_id" ref="project.project_task_29"/>
|
||||
<field name="name">Daily Meetings summary</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
</record>
|
||||
<record id="project_task_31" model="project.task">
|
||||
<field name="sequence">20</field>
|
||||
<field name="planned_hours">2.0</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="parent_id" ref="project.project_task_29"/>
|
||||
<field name="name">Preparation</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
</record>
|
||||
<record id="project_task_32" model="project.task">
|
||||
<field name="sequence">30</field>
|
||||
<field name="planned_hours">2.0</field>
|
||||
<field name="user_ids" eval="False"/>
|
||||
<field name="project_id" ref="project.project_project_1"/>
|
||||
<field name="parent_id" ref="project.project_task_29"/>
|
||||
<field name="name">Minutes</field>
|
||||
<field name="stage_id" ref="project_stage_1"/>
|
||||
</record>
|
||||
|
||||
<function model="project.task.recurrence" name="_cron_create_recurring_tasks"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -1419,8 +1419,9 @@ class Task(models.Model):
|
||||
|
||||
@api.constrains('recurring_task')
|
||||
def _check_recurring_task(self):
|
||||
if self.filtered(lambda task: task.parent_id and task.recurring_task):
|
||||
raise ValidationError(_("A sub-task cannot be a recurring task. Please consider making its parent task, a recurring task."))
|
||||
# Deprecated method
|
||||
# TODO : Remove me in master
|
||||
return
|
||||
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def copy(self, default=None):
|
||||
|
||||
@@ -458,3 +458,71 @@ class TestProjectrecurrence(TransactionCase):
|
||||
self.assertEqual(dates[2], datetime(2023, 11, 30))
|
||||
self.assertEqual(dates[3], datetime(2024, 11, 30))
|
||||
self.assertEqual(dates[4], datetime(2025, 11, 30))
|
||||
|
||||
def test_recurrence_cron_repeat_after_subtasks(self):
|
||||
|
||||
def get_task_and_subtask_counts(domain):
|
||||
tasks = self.env['project.task'].search(domain)
|
||||
return len(tasks), len(tasks.filtered('parent_id'))
|
||||
|
||||
parent_task = self.env['project.task'].create({
|
||||
'name': 'Parent Task',
|
||||
'project_id': self.project_recurring.id
|
||||
})
|
||||
domain = [('project_id', '=', self.project_recurring.id)]
|
||||
with Form(parent_task.with_context({'tracking_disable': True})) as task_form:
|
||||
with task_form.child_ids.new() as subtask_form:
|
||||
subtask_form.name = 'Test Subtask 1'
|
||||
with freeze_time("2020-01-01"):
|
||||
with Form(parent_task.child_ids.with_context({'tracking_disable': True})) as form:
|
||||
form.description = 'my super recurring task bla bla bla'
|
||||
form.date_deadline = datetime(2020, 2, 1)
|
||||
|
||||
form.recurring_task = True
|
||||
form.repeat_interval = 1
|
||||
form.repeat_unit = 'month'
|
||||
form.repeat_type = 'after'
|
||||
form.repeat_number = 2
|
||||
form.repeat_on_month = 'date'
|
||||
form.repeat_day = '15'
|
||||
subtask = form.save()
|
||||
subtask.planned_hours = 2
|
||||
|
||||
self.assertEqual(subtask.recurrence_id.next_recurrence_date, date(2020, 1, 15))
|
||||
project_task_count, project_subtask_count = get_task_and_subtask_counts(domain)
|
||||
self.assertEqual(project_task_count, 2)
|
||||
self.assertEqual(project_subtask_count, 1)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
self.assertEqual(self.env['project.task'].search_count(domain), 2, 'no extra task should be created')
|
||||
self.assertEqual(subtask.recurrence_id.recurrence_left, 2)
|
||||
|
||||
with freeze_time("2020-01-15"):
|
||||
project_task_count, project_subtask_count = get_task_and_subtask_counts(domain)
|
||||
self.assertEqual(project_task_count, 2)
|
||||
self.assertEqual(project_subtask_count, 1)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
project_task_count, project_subtask_count = get_task_and_subtask_counts(domain)
|
||||
self.assertEqual(project_task_count, 3)
|
||||
self.assertEqual(project_subtask_count, 2)
|
||||
self.assertEqual(subtask.recurrence_id.recurrence_left, 1)
|
||||
|
||||
with freeze_time("2020-02-15"):
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
project_task_count, project_subtask_count = get_task_and_subtask_counts(domain)
|
||||
self.assertEqual(project_task_count, 4)
|
||||
self.assertEqual(project_subtask_count, 3)
|
||||
self.assertEqual(subtask.recurrence_id.recurrence_left, 0)
|
||||
self.env['project.task.recurrence']._cron_create_recurring_tasks()
|
||||
project_task_count, project_subtask_count = get_task_and_subtask_counts(domain)
|
||||
self.assertEqual(project_task_count, 4)
|
||||
self.assertEqual(project_subtask_count, 3)
|
||||
self.assertEqual(subtask.recurrence_id.recurrence_left, 0)
|
||||
|
||||
tasks = self.env['project.task'].search(domain)
|
||||
self.assertEqual(len(tasks), 4)
|
||||
|
||||
self.assertTrue(bool(tasks[2].date_deadline))
|
||||
self.assertFalse(tasks[1].date_deadline, "Deadline should not be copied")
|
||||
|
||||
for f in self.env['project.task.recurrence']._get_recurring_fields():
|
||||
self.assertTrue(tasks[0][f] == tasks[1][f] == tasks[2][f], "Field %s should have been copied" % f)
|
||||
|
||||
@@ -852,7 +852,7 @@
|
||||
<field name="partner_phone" widget="phone" attrs="{'invisible': True}"/>
|
||||
<field name="date_deadline" attrs="{'invisible': [('is_closed', '=', True)]}"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
|
||||
<field name="recurring_task" attrs="{'invisible': ['|', ('allow_recurring_tasks', '=', False), ('parent_id', '!=', False)]}" />
|
||||
<field name="recurring_task" attrs="{'invisible': [('allow_recurring_tasks', '=', False)]}" />
|
||||
<field name="legend_blocked" invisible="1"/>
|
||||
<field name="legend_normal" invisible="1"/>
|
||||
<field name="legend_done" invisible="1"/>
|
||||
|
||||
Reference in New Issue
Block a user