Merge pull request #37025 from s-aga-r/FIX-883

fix: `Parent Task` link with `Project Task`
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index c2ed579..a66b549 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -87,6 +87,7 @@
 				issue=task_details.issue,
 				is_group=task_details.is_group,
 				color=task_details.color,
+				template_task=task_details.name,
 			)
 		).insert()
 
@@ -106,9 +107,13 @@
 		return date
 
 	def dependency_mapping(self, template_tasks, project_tasks):
-		for template_task in template_tasks:
-			project_task = list(filter(lambda x: x.subject == template_task.subject, project_tasks))[0]
-			project_task = frappe.get_doc("Task", project_task.name)
+		for project_task in project_tasks:
+			if project_task.get("template_task"):
+				template_task = frappe.get_doc("Task", project_task.template_task)
+			else:
+				template_task = list(filter(lambda x: x.subject == project_task.subject, template_tasks))[0]
+				template_task = frappe.get_doc("Task", template_task.name)
+
 			self.check_depends_on_value(template_task, project_task, project_tasks)
 			self.check_for_parent_tasks(template_task, project_task, project_tasks)
 
@@ -120,6 +125,7 @@
 					filter(lambda x: x.subject == child_task_subject, project_tasks)
 				)
 				if len(corresponding_project_task):
+					project_task.reload()  # reload, as it might have been updated in the previous iteration
 					project_task.append("depends_on", {"task": corresponding_project_task[0].name})
 					project_task.save()
 
diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py
index 8a599ce..e49fecd 100644
--- a/erpnext/projects/doctype/project/test_project.py
+++ b/erpnext/projects/doctype/project/test_project.py
@@ -1,9 +1,8 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
-import unittest
-
 import frappe
+from frappe.tests.utils import FrappeTestCase
 from frappe.utils import add_days, getdate, nowdate
 
 from erpnext.projects.doctype.project_template.test_project_template import make_project_template
@@ -15,7 +14,7 @@
 test_ignore = ["Sales Order"]
 
 
-class TestProject(unittest.TestCase):
+class TestProject(FrappeTestCase):
 	def test_project_with_template_having_no_parent_and_depend_tasks(self):
 		project_name = "Test Project with Template - No Parent and Dependend Tasks"
 		frappe.db.sql(""" delete from tabTask where project = %s """, project_name)
@@ -155,6 +154,50 @@
 		so.reload()
 		self.assertFalse(so.project)
 
+	def test_project_with_template_tasks_having_common_name(self):
+		# Step - 1: Create Template Parent Tasks
+		template_parent_task1 = create_task(subject="Parent Task - 1", is_template=1, is_group=1)
+		template_parent_task2 = create_task(subject="Parent Task - 2", is_template=1, is_group=1)
+		template_parent_task3 = create_task(subject="Parent Task - 1", is_template=1, is_group=1)
+
+		# Step - 2: Create Template Child Tasks
+		template_task1 = create_task(
+			subject="Task - 1", is_template=1, parent_task=template_parent_task1.name
+		)
+		template_task2 = create_task(
+			subject="Task - 2", is_template=1, parent_task=template_parent_task2.name
+		)
+		template_task3 = create_task(
+			subject="Task - 1", is_template=1, parent_task=template_parent_task3.name
+		)
+
+		# Step - 3: Create Project Template
+		template_tasks = [
+			template_parent_task1,
+			template_task1,
+			template_parent_task2,
+			template_task2,
+			template_parent_task3,
+			template_task3,
+		]
+		project_template = make_project_template(
+			"Project template with common Task Subject", template_tasks
+		)
+
+		# Step - 4: Create Project against the Project Template
+		project = get_project("Project with common Task Subject", project_template)
+		project_tasks = frappe.get_all(
+			"Task", {"project": project.name}, ["subject", "parent_task", "is_group"]
+		)
+
+		# Test - 1: No. of Project Tasks should be equal to No. of Template Tasks
+		self.assertEquals(len(project_tasks), len(template_tasks))
+
+		# Test - 2: All child Project Tasks should have Parent Task linked
+		for pt in project_tasks:
+			if not pt.is_group:
+				self.assertIsNotNone(pt.parent_task)
+
 
 def get_project(name, template):
 
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index 62ec9e0..05a70c3 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -52,13 +52,15 @@
   "company",
   "lft",
   "rgt",
-  "old_parent"
+  "old_parent",
+  "template_task"
  ],
  "fields": [
   {
    "fieldname": "subject",
    "fieldtype": "Data",
    "in_global_search": 1,
+   "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Subject",
    "reqd": 1,
@@ -138,6 +140,7 @@
    "fieldname": "parent_task",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
+   "in_list_view": 1,
    "label": "Parent Task",
    "options": "Task",
    "search_index": 1
@@ -382,6 +385,12 @@
    "fieldtype": "Date",
    "label": "Completed On",
    "mandatory_depends_on": "eval: doc.status == \"Completed\""
+  },
+  {
+   "fieldname": "template_task",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Template Task"
   }
  ],
  "icon": "fa fa-check",
@@ -389,7 +398,7 @@
  "is_tree": 1,
  "links": [],
  "max_attachments": 5,
- "modified": "2023-04-17 21:06:50.174418",
+ "modified": "2023-09-06 13:52:05.861175",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Task",