From b5aaa156c2fc7fef9c403a61e8c903f9fc0a2b9a Mon Sep 17 00:00:00 2001 From: Atte Isopuro Date: Tue, 5 Mar 2024 17:20:48 +0200 Subject: [PATCH] [FIX] project_template: preserve task end_date Previously, if multiple tasks in a template project had the same name, their end_date-values were not copied properly. --- project_template/models/project.py | 21 ++++++---- .../tests/test_project_template.py | 39 +++++++++++++++++-- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/project_template/models/project.py b/project_template/models/project.py index f24b5113e2..4f8c6437eb 100644 --- a/project_template/models/project.py +++ b/project_template/models/project.py @@ -1,6 +1,9 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import api, fields, models +# See _map_tasks_default_valeus +TASK_DEFAULT_COPY_CONTEXT_KEY = f"{__name__}.task_default_copy_context_key" + class Project(models.Model): _inherit = "project.project" @@ -13,17 +16,10 @@ def create_project_from_template(self): new_name = self.name.replace(" (TEMPLATE)", " (COPY)") else: new_name = self.name + " (COPY)" - new_project = self.copy( + new_project = self.with_context(**{TASK_DEFAULT_COPY_CONTEXT_KEY: True}).copy( default={"name": new_name, "active": True, "alias_name": False} ) - # SINCE THE END DATE DOESN'T COPY OVER ON TASKS - # (Even when changed to copy=true), POPULATE END DATES ON THE TASK - for new_task_record in new_project.task_ids: - for old_task_record in self.task_ids: - if new_task_record.name == old_task_record.name: - new_task_record.date_end = old_task_record.date_end - # OPEN THE NEWLY CREATED PROJECT FORM return { "view_type": "form", @@ -34,6 +30,15 @@ def create_project_from_template(self): "type": "ir.actions.act_window", } + @api.model + def _map_tasks_default_valeus(self, task, project): + defaults = super()._map_tasks_default_valeus(task, project) + if self.env.context.get(TASK_DEFAULT_COPY_CONTEXT_KEY): + # date_end normally is not copied on tasks when a project is + # copied, but we want it when generating from template + defaults["date_end"] = task.date_end + return defaults + # ADD "(TEMPLATE)" TO THE NAME WHEN PROJECT IS MARKED AS A TEMPLATE @api.onchange("is_template") def on_change_is_template(self): diff --git a/project_template/tests/test_project_template.py b/project_template/tests/test_project_template.py index c6a17bb209..9a56c25f31 100644 --- a/project_template/tests/test_project_template.py +++ b/project_template/tests/test_project_template.py @@ -1,5 +1,6 @@ # Copyright 2019 Patrick Wilson # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from datetime import datetime, timedelta from odoo.tests import common @@ -15,9 +16,14 @@ def setUp(self): "partner_id": self.test_customer.id, } ) - self.env["project.task"].create( - {"name": "TestTask", "project_id": self.test_project.id} - ) + self.tasks = [ + self.env["project.task"].create( + {"name": "TestTask", "project_id": self.test_project.id} + ), + self.env["project.task"].create( + {"name": "TestTask2", "project_id": self.test_project.id} + ), + ] # TEST 01: Set project to be a template and test name change def test_on_change_is_template(self): @@ -61,3 +67,30 @@ def test_create_project_from_template_non_standard_name(self): [("name", "=", "TestProject(TEST) (COPY)")] ) self.assertEqual(len(new_project), 1) + + def test_create_project_from_template_duplicate_task_names(self): + project_01 = self.test_project + project_01.is_template = True + project_01.on_change_is_template() + # Set the same name on all tasks + dates = set() + now = datetime.now() + for i, task in enumerate(self.tasks): + date = now - timedelta(weeks=i) + task.name = "Same for all tasks" + dates.add(date) + task.date_end = date + + # Create new Project from Template + project_01.create_project_from_template() + new_project = self.env["project.project"].search( + [("name", "=", "TestProject (COPY)")] + ) + self.assertEqual(len(new_project), 1) + new_tasks = self.env["project.task"].search( + [ + ("project_id", "=", new_project.id), + ] + ) + self.assertEqual(len(new_tasks), len(self.tasks)) + self.assertEqual(set(new_tasks.mapped("date_end")), dates)