From d32412421fd2b2bc8c19c7ab543c8c5770519a97 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Pacharla Date: Tue, 22 Jul 2025 13:09:55 +0530 Subject: [PATCH 1/3] [feat]: implemented logic to add service template rows on project --- .../doctype/sales_order/sales_order.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 9543cec79e57..faafcb131790 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -93,6 +93,7 @@ def on_submit(self): self.update_blanket_order() update_linked_doc(self.doctype, self.name, self.inter_company_reference) + self.add_service_template_rows() if self.coupon_code: from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count update_coupon_code_count(self.coupon_code, 'used') @@ -913,6 +914,46 @@ def validate_serial_no_based_delivery(self): Item {0} is added with and without Ensure Delivery by \ Serial No.").format(item.item_code)) + def add_service_template_rows(self): + project_name = self.get("project") + if not project_name: + return + + project = frappe.get_doc("Project", project_name) + updated = False + service_template_rows = [] + + for item in self.items: + service_template = item.get("service_template") + if not service_template: + continue + + existing_service_template_row = next((row for row in project.service_templates if row.service_template == service_template), None) + if existing_service_template_row: + is_service_template_row_linked = frappe.db.exists("Sales Order Item", {"service_template_detail": existing_service_template_row.name}) + + if is_service_template_row_linked: + frappe.throw( + f"Service template: {service_template} already linked to item: {item.item_name} and will not be linked to new sales order.") + continue + + new_service_template_row = project.append("service_templates", { + "service_template": service_template, + "has_sales_order": 1, + "sales_order": self.name, + }) + service_template_rows.append((item.name, new_service_template_row)) + updated = True + + if updated: + project.save(ignore_permissions=True) + + for item_name, service_template_row in service_template_rows: + if service_template_row.name: + frappe.db.set_value("Sales Order Item", item_name, "service_template_detail", service_template_row.name) + + project.set_service_template_has_transaction(update=True) + @frappe.whitelist() def update_status(status, name): From 4eaf366942065afcd72dd06e531545d377d8e761 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Pacharla Date: Thu, 24 Jul 2025 18:40:07 +0530 Subject: [PATCH 2/3] [feat]: (#491) refactored code --- .../selling/doctype/sales_order/sales_order.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index faafcb131790..cb0a6871dffb 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -934,25 +934,27 @@ def add_service_template_rows(self): if is_service_template_row_linked: frappe.throw( - f"Service template: {service_template} already linked to item: {item.item_name} and will not be linked to new sales order.") + _("Service template: {0} already linked to item: {1} and will not be linked to new sales order.").format(service_template, item.item_name)) continue new_service_template_row = project.append("service_templates", { "service_template": service_template, "has_sales_order": 1, - "sales_order": self.name, }) service_template_rows.append((item.name, new_service_template_row)) updated = True - if updated: - project.save(ignore_permissions=True) + if not updated: + return + + for service_template_row in service_template_rows: + service_template_row[1].insert(ignore_permissions=True) - for item_name, service_template_row in service_template_rows: - if service_template_row.name: - frappe.db.set_value("Sales Order Item", item_name, "service_template_detail", service_template_row.name) + for item_name, service_template_row in service_template_rows: + if service_template_row.name: + frappe.db.set_value("Sales Order Item", item_name, "service_template_detail", service_template_row.name) - project.set_service_template_has_transaction(update=True) + project.set_service_template_has_transaction(update=True) @frappe.whitelist() From d9e0f099a87c1a040edf9998a5b13e8cab4e2c59 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Pacharla Date: Mon, 4 Aug 2025 17:55:27 +0530 Subject: [PATCH 3/3] [feat]: (#491) added extra lines --- erpnext/selling/doctype/sales_order/sales_order.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index cb0a6871dffb..7f8a3338c2fe 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -916,6 +916,7 @@ def validate_serial_no_based_delivery(self): def add_service_template_rows(self): project_name = self.get("project") + if not project_name: return @@ -941,6 +942,7 @@ def add_service_template_rows(self): "service_template": service_template, "has_sales_order": 1, }) + service_template_rows.append((item.name, new_service_template_row)) updated = True