Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion erpnext/projects/doctype/service_template/service_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from frappe import _
from frappe.model.document import Document
from frappe.utils import cint, clean_whitespace, cstr
from erpnext.projects.utils import validate_comma_separated_indices, check_for_circular_dependencies
import json


Expand All @@ -15,6 +16,7 @@ def validate(self):
self.validate_duplicate_applicable_item_groups()
self.validate_due_after()
self.validate_service_warranty()
self.validate_task_dependencies()

def onload(self):
pass
Expand Down Expand Up @@ -86,6 +88,16 @@ def filter_applicable_item(self, pt_item, applies_to_item=None, applies_to_custo

return False

def validate_task_dependencies(self):
max_idx = max((row.idx for row in self.tasks if row.idx), default=0)
dependency_map = {}

for row in self.tasks:
dep_indices = validate_comma_separated_indices(row.depends_on_task, row.idx, max_allowed_idx=max_idx)
dependency_map[row.idx] = dep_indices

check_for_circular_dependencies(dependency_map)


@frappe.whitelist()
def get_service_template_details(service_template):
Expand Down Expand Up @@ -219,7 +231,7 @@ def get_service_template_tasks(
'service_template_name': service_template_doc.service_template_name,
})

for template_task_row in service_template_doc.tasks:
for idx, template_task_row in enumerate(service_template_doc.tasks):
task_details = frappe._dict()
task_details.subject = template_task_row.subject
task_details.description = template_task_row.description
Expand All @@ -228,6 +240,8 @@ def get_service_template_tasks(
task_details.service_template = service_template_detail.service_template
task_details.service_template_detail = service_template_detail.name
task_details.determine_time = template_task_row.determine_time
task_details.depends_on_task = template_task_row.depends_on_task or ""
task_details.idx = idx + 1

if template_task_row.use_template_name:
task_details.subject = service_template_detail.service_template_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"field_order": [
"subject",
"task_type",
"depends_on_task",
"column_break_l9vb",
"expected_time",
"determine_time",
Expand All @@ -17,7 +18,7 @@
],
"fields": [
{
"columns": 6,
"columns": 4,
"fieldname": "subject",
"fieldtype": "Data",
"in_list_view": 1,
Expand Down Expand Up @@ -69,11 +70,17 @@
"fieldname": "use_template_description",
"fieldtype": "Check",
"label": "Use Template Description"
},
{
"fieldname": "depends_on_task",
"fieldtype": "Data",
"label": "Depends On Task",
"in_list_view": 1
}
],
"istable": 1,
"links": [],
"modified": "2025-02-01 13:22:34.628230",
"modified": "2025-07-07 14:00:59.617902",
"modified_by": "Administrator",
"module": "Projects",
"name": "Service Template Task",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,24 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
import frappe
from frappe.model.document import Document
from frappe import _

class ServiceTemplateTask(Document):
pass
def validate_depends_on_task(self):
if not self.depends_on_task:
return

parts = [x.strip() for x in self.depends_on_task.split(',') if x.strip()]
for part in parts:
if not part.isdigit():
frappe.throw(
_("Row #{0}: 'Depends On Task' must only contain comma-separated numbers. Found invalid value: {1}").format(
self.idx, part))

invalid_indices = [int(x) for x in parts if int(x) >= self.idx]
if invalid_indices:
frappe.throw(_("Row #{0}: 'Depends On Task' cannot refer to current or future rows: {1}").format(
self.idx, ", ".join(str(x) for x in invalid_indices)
))
8 changes: 8 additions & 0 deletions erpnext/projects/doctype/task/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ erpnext.projects.TaskController = class TaskController extends frappe.ui.form.Co
}, __("Actions"));
}

if (this.get_action_condition("rework_task")) {
this.frm.add_custom_button(__("Create Rework Task"), () => {
this.frm.check_if_unsaved();
return erpnext.task_actions.create_rework_task(this.frm.doc.name, this.frm.doc, null,
() => this.frm.reload_doc());
}, __("Actions"));
}

if (this.get_action_condition("cancel_task")) {
this.frm.add_custom_button(__("Cancel"), () => {
this.frm.check_if_unsaved();
Expand Down
43 changes: 42 additions & 1 deletion erpnext/projects/doctype/task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
"status",
"progress",
"priority",
"rework_section",
"rework_of",
"rework_column_break",
"rework_reason",
"is_rework_task",
"assignment_section",
"assigned_to",
"assigned_to_name",
Expand Down Expand Up @@ -542,14 +547,50 @@
{
"fieldname": "column_break_mwlw",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "is_rework_task",
"fieldtype": "Check",
"hidden": 1,
"label": "Is Rework Task",
"read_only": 1
},
{
"depends_on": "is_rework_task",
"fieldname": "rework_of",
"fieldtype": "Link",
"label": "Rework For",
"mandatory_depends_on": "is_rework_task",
"options": "Task"
},
{
"depends_on": "is_rework_task",
"fieldname": "rework_reason",
"fieldtype": "Small Text",
"label": "Rework Reason",
"mandatory_depends_on": "is_rework_task"
},
{
"depends_on": "is_rework_task",
"fieldname": "rework_section",
"fieldtype": "Section Break",
"label": "Rework"
},
{
"fieldname": "rework_column_break",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
"width": "50%"
}
],
"icon": "fa fa-check",
"idx": 1,
"is_calendar_and_gantt": 1,
"is_tree": 1,
"links": [],
"modified": "2025-07-02 12:29:30.295539",
"modified": "2025-07-11 11:25:29.385970",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
Expand Down
Loading