From 5e66231ca4e8dc93659f229843fd632181408ca9 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 20 Feb 2025 15:03:19 +0530 Subject: [PATCH 1/4] perf: replace if function in query --- erpnext/projects/doctype/project/project.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 5706edcda63..417c73ec685 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -325,10 +325,10 @@ class Project(Document): # nosemgrep total_billed_amount = frappe.db.sql( """select sum(base_net_amount) - from `tabSales Invoice Item` si_item, `tabSales Invoice` si - where si_item.parent = si.name - and if(si_item.project, si_item.project, si.project) = %s - and si.docstatus=1""", + from `tabSales Invoice Item` si_item + join `tabSales Invoice` si on si_item.parent = si.name + where (si_item.project = %s or (si_item.project is null and si.project = %s)) + and si.docstatus = 1""", self.name, ) From 2f1e253e19109cd12d25a3e7d643344663bcf340 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 20 Feb 2025 15:28:13 +0530 Subject: [PATCH 2/4] fix: syntax error --- erpnext/projects/doctype/project/project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 417c73ec685..f9eace85147 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -327,9 +327,9 @@ class Project(Document): """select sum(base_net_amount) from `tabSales Invoice Item` si_item join `tabSales Invoice` si on si_item.parent = si.name - where (si_item.project = %s or (si_item.project is null and si.project = %s)) + where (si_item.project = %(name)s or (si_item.project is null and si.project = %(name)s)) and si.docstatus = 1""", - self.name, + {"name": self.name}, ) self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0 From f7594e2ff99a1fbc4b320b7aa4372ea7389068cc Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 21 Feb 2025 11:02:38 +0530 Subject: [PATCH 3/4] fix: revamp logic (split parent and child) --- erpnext/projects/doctype/project/project.py | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index f9eace85147..959b34f77a3 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -322,17 +322,31 @@ class Project(Document): self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0 def update_billed_amount(self): - # nosemgrep + self.total_billed_amount = self.get_billed_amount_from_parent() + self.get_billed_amount_from_child() + + def get_billed_amount_from_parent(self): total_billed_amount = frappe.db.sql( """select sum(base_net_amount) - from `tabSales Invoice Item` si_item - join `tabSales Invoice` si on si_item.parent = si.name - where (si_item.project = %(name)s or (si_item.project is null and si.project = %(name)s)) - and si.docstatus = 1""", - {"name": self.name}, + from `tabSales Invoice` si join `tabSales Invoice Item` si_item on si_item.parent = si.name + where si_item.project is null + and si.project is not null + and si.project = %s + and si.docstatus = 1""", + self.name, ) - self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0 + return total_billed_amount and total_billed_amount[0][0] or 0 + + def get_billed_amount_from_child(self): + total_billed_amount = frappe.db.sql( + """select sum(base_net_amount) + from `tabSales Invoice Item` + where project = %s + and docstatus = 1""", + self.name, + ) + + return total_billed_amount and total_billed_amount[0][0] or 0 def after_rename(self, old_name, new_name, merge=False): if old_name == self.copied_from: From 6073f5a6f95f5f0fdeae21e0bdd869eddf34cb85 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Sun, 23 Feb 2025 22:26:01 +0530 Subject: [PATCH 4/4] test: added test --- .../sales_invoice/test_sales_invoice.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index de488aebcbf..9ee30acbb77 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -4305,6 +4305,31 @@ class TestSalesInvoice(IntegrationTestCase): doc = frappe.get_doc("Project", project.name) self.assertEqual(doc.total_billed_amount, si.grand_total) + def test_total_billed_amount_with_different_projects(self): + # This test case is for checking the scenario where project is set at document level and for **some** child items only, not all + from copy import copy + + si = create_sales_invoice(do_not_submit=True) + + project = frappe.new_doc("Project") + project.company = "_Test Company" + project.project_name = "Test Total Billed Amount" + project.save() + + si.project = project.name + si.items.append(copy(si.items[0])) + si.items.append(copy(si.items[0])) + si.items[0].project = project.name + si.items[1].project = project.name + # Not setting project on last item + si.items[1].insert() + si.items[2].insert() + si.submit() + + project.reload() + self.assertIsNone(si.items[2].project) + self.assertEqual(project.total_billed_amount, 300) + def test_pos_returns_with_party_account_currency(self): from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return