From 3380deab02382fb043daa19c90d84204ad560e40 Mon Sep 17 00:00:00 2001 From: Pugazhendhi Velu Date: Tue, 4 Nov 2025 08:30:54 +0000 Subject: [PATCH 1/4] fix: validate is_group for parent task (cherry picked from commit ed1a1099cb53d336413b1e4df95cb5d46bddd5a2) # Conflicts: # erpnext/projects/doctype/task/task.py --- erpnext/projects/doctype/task/task.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 5eae55d71c5..5434b509624 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -17,6 +17,10 @@ class CircularReferenceError(frappe.ValidationError): pass +class ParentIsGroupError(frappe.ValidationError): + pass + + class Task(NestedSet): # begin: auto-generated types # This code is auto-generated. Do not modify anything in this block. @@ -83,6 +87,11 @@ class Task(NestedSet): self.update_depends_on() self.validate_dependencies_for_template_task() self.validate_completed_on() +<<<<<<< HEAD +======= + self.set_default_end_date_if_missing() + self.validate_parent_is_group() +>>>>>>> ed1a1099cb (fix: validate is_group for parent task) def validate_dates(self): self.validate_from_to_dates("exp_start_date", "exp_end_date") @@ -167,6 +176,14 @@ class Task(NestedSet): if self.completed_on and getdate(self.completed_on) > getdate(): frappe.throw(_("Completed On cannot be greater than Today")) + def validate_parent_is_group(self): + if self.parent_task: + if not frappe.db.get_value("Task", self.parent_task, "is_group"): + parent_task_format = f"""{self.parent_task}""" + frappe.throw( + _("Parent Task {0} must be a Group Task").format(parent_task_format), ParentIsGroupError + ) + def update_depends_on(self): depends_on_tasks = "" for d in self.depends_on: From dc5b8367c52810a6e7dc9518e951fd45aa82a497 Mon Sep 17 00:00:00 2001 From: Pugazhendhi Velu Date: Tue, 4 Nov 2025 08:31:41 +0000 Subject: [PATCH 2/4] test: add test for parent task is_group validation (cherry picked from commit 291f0c71613236cdbc92aff9979d13c4bca23817) # Conflicts: # erpnext/projects/doctype/task/test_task.py --- erpnext/projects/doctype/task/test_task.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index b0194b08dfa..0cb4348a2cb 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -6,7 +6,12 @@ import unittest import frappe from frappe.utils import add_days, getdate, nowdate +<<<<<<< HEAD from erpnext.projects.doctype.task.task import CircularReferenceError +======= +from erpnext.projects.doctype.task.task import CircularReferenceError, ParentIsGroupError +from erpnext.tests.utils import ERPNextTestSuite +>>>>>>> 291f0c7161 (test: add test for parent task is_group validation) class TestTask(unittest.TestCase): @@ -109,6 +114,20 @@ class TestTask(unittest.TestCase): self.assertEqual(frappe.db.get_value("Task", task.name, "status"), "Overdue") + def test_parent_task_must_be_group(self): + parent_task = create_task( + subject="_Test Parent Task Non Group", + is_group=0, + ) + + child_task = create_task( + subject="_Test Child Task", + parent_task=parent_task.name, + save=False, + ) + + self.assertRaises(ParentIsGroupError, child_task.save) + def create_task( subject, From 635fe427fe51de98486a95a74bb322eba2cec6b1 Mon Sep 17 00:00:00 2001 From: Pugazhendhi Velu Date: Thu, 6 Nov 2025 11:22:58 +0000 Subject: [PATCH 3/4] refactor(task): use get_link_to_form for validation error messages (cherry picked from commit 4cf02b4d78980c34b0de66aaac169681a4651577) --- erpnext/projects/doctype/task/task.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 5434b509624..ce324513951 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -162,15 +162,21 @@ class Task(NestedSet): def validate_parent_template_task(self): if self.parent_task: if not frappe.db.get_value("Task", self.parent_task, "is_template"): - parent_task_format = f"""{self.parent_task}""" - frappe.throw(_("Parent Task {0} is not a Template Task").format(parent_task_format)) + frappe.throw( + _("Parent Task {0} is not a Template Task").format( + get_link_to_form("Task", self.parent_task) + ) + ) def validate_depends_on_tasks(self): if self.depends_on: for task in self.depends_on: if not frappe.db.get_value("Task", task.task, "is_template"): - dependent_task_format = f"""{task.task}""" - frappe.throw(_("Dependent Task {0} is not a Template Task").format(dependent_task_format)) + frappe.throw( + _("Dependent Task {0} is not a Template Task").format( + get_link_to_form("Task", task.task) + ) + ) def validate_completed_on(self): if self.completed_on and getdate(self.completed_on) > getdate(): @@ -179,9 +185,11 @@ class Task(NestedSet): def validate_parent_is_group(self): if self.parent_task: if not frappe.db.get_value("Task", self.parent_task, "is_group"): - parent_task_format = f"""{self.parent_task}""" frappe.throw( - _("Parent Task {0} must be a Group Task").format(parent_task_format), ParentIsGroupError + _("Parent Task {0} must be a Group Task").format( + get_link_to_form("Task", self.parent_task) + ), + ParentIsGroupError, ) def update_depends_on(self): From df6ca3af57d9104a7f84acd386883745625ca6b9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 10 Nov 2025 12:43:05 +0530 Subject: [PATCH 4/4] chore: resolve conflicts --- erpnext/projects/doctype/task/task.py | 4 ---- erpnext/projects/doctype/task/test_task.py | 5 ----- 2 files changed, 9 deletions(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index ce324513951..7eb55272eb8 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -87,11 +87,7 @@ class Task(NestedSet): self.update_depends_on() self.validate_dependencies_for_template_task() self.validate_completed_on() -<<<<<<< HEAD -======= - self.set_default_end_date_if_missing() self.validate_parent_is_group() ->>>>>>> ed1a1099cb (fix: validate is_group for parent task) def validate_dates(self): self.validate_from_to_dates("exp_start_date", "exp_end_date") diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 0cb4348a2cb..bf5852834b2 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -6,12 +6,7 @@ import unittest import frappe from frappe.utils import add_days, getdate, nowdate -<<<<<<< HEAD -from erpnext.projects.doctype.task.task import CircularReferenceError -======= from erpnext.projects.doctype.task.task import CircularReferenceError, ParentIsGroupError -from erpnext.tests.utils import ERPNextTestSuite ->>>>>>> 291f0c7161 (test: add test for parent task is_group validation) class TestTask(unittest.TestCase):