From c18ca7af2242d3c7fea8b9d0eb724ac69964c10e Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 19 Jun 2026 21:21:08 +0530 Subject: [PATCH] refactor(postgres): port quality_procedure on_trash to the query builder Co-Authored-By: Claude Opus 4.8 (1M context) --- .../quality_procedure/quality_procedure.py | 7 ++-- .../test_quality_procedure.py | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py index b98442fe92a..41e4412f799 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py @@ -49,11 +49,8 @@ class QualityProcedure(NestedSet): def on_trash(self): # clear from child table (sub procedures) - frappe.db.sql( - """update `tabQuality Procedure Process` - set `procedure`='' where `procedure`=%s""", - self.name, - ) + qpp = frappe.qb.DocType("Quality Procedure Process") + frappe.qb.update(qpp).set(qpp["procedure"], "").where(qpp["procedure"] == self.name).run() NestedSet.on_trash(self, allow_root_deletion=True) def check_for_incorrect_child(self): diff --git a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py index e4d847159f6..61e0da093cd 100644 --- a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py @@ -65,6 +65,40 @@ class TestQualityProcedure(ERPNextTestSuite): child_qp.reload() self.assertEqual(child_qp.parent_quality_procedure, None) + def test_on_trash_clears_referencing_process(self): + # Build a parent group with a sub-procedure. The parent's child table gets a + # `Quality Procedure Process` row whose `procedure` field points at the child. + child_qp = create_procedure( + { + "quality_procedure_name": "Test Child On Trash", + "is_group": 0, + } + ) + create_procedure( + { + "quality_procedure_name": "Test Group On Trash", + "is_group": 1, + "processes": [dict(procedure=child_qp.name)], + } + ) + + # Sanity: a process row in the parent references the child by name. + referencing_rows = frappe.get_all( + "Quality Procedure Process", + filters={"procedure": child_qp.name}, + pluck="name", + ) + self.assertTrue(referencing_rows) + + # Deleting the child runs on_trash() -> the converted UPDATE clears `procedure`. + child_qp.delete() + + for row_name in referencing_rows: + self.assertEqual( + frappe.db.get_value("Quality Procedure Process", row_name, "procedure"), + "", + ) + def remove_child_from_old_parent(self): child_qp = create_procedure( {