fix: Calculate gross margin on update of project costing from invoices (backport #43876) (#43900)

* fix: Calculate gross margin on update of project costing from invoices (#43876)

* fix: Calculate gross margin on update of project costing from invoices

* chore: linter issues

(cherry picked from commit 0bba6442c0)

# Conflicts:
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json

* fix: merge conflict

---------

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
mergify[bot]
2024-10-29 22:36:39 +05:30
committed by GitHub
parent cd4746ad2a
commit 93d0db2910
5 changed files with 26 additions and 38 deletions

View File

@@ -1593,7 +1593,11 @@ class PurchaseInvoice(BuyingController):
for proj, value in projects.items():
res = frappe.qb.from_(pj).select(pj.total_purchase_cost).where(pj.name == proj).for_update().run()
current_purchase_cost = res and res[0][0] or 0
frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
# frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
project_doc = frappe.get_doc("Project", proj)
project_doc.total_purchase_cost = current_purchase_cost + value
project_doc.calculate_gross_margin()
project_doc.db_update()
def validate_supplier_invoice(self):
if self.bill_date:

View File

@@ -505,7 +505,8 @@
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"print_hide": 1
"print_hide": 1,
"search_index": 1
},
{
"allow_on_submit": 1,
@@ -974,7 +975,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-07-19 12:12:42.449298",
"modified": "2024-10-28 15:06:19.246141",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -1734,9 +1734,11 @@ class SalesInvoice(SellingController):
)
def update_project(self):
if self.project:
project = frappe.get_doc("Project", self.project)
unique_projects = list(set([d.project for d in self.get("items") if d.project]))
for p in unique_projects:
project = frappe.get_doc("Project", p)
project.update_billed_amount()
project.calculate_gross_margin()
project.db_update()
def verify_payment_amount_is_positive(self):

View File

@@ -812,7 +812,8 @@
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
"options": "Project",
"search_index": 1
},
{
"depends_on": "eval:parent.update_stock == 1",
@@ -927,7 +928,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-05-23 16:36:18.970862",
"modified": "2024-10-28 15:06:40.980995",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -93,14 +93,14 @@ class Project(Document):
def validate(self):
if not self.is_new():
self.copy_from_template()
self.copy_from_template() # nosemgrep
self.send_welcome_email()
self.update_costing()
self.update_percent_complete()
self.validate_from_to_dates("expected_start_date", "expected_end_date")
self.validate_from_to_dates("actual_start_date", "actual_end_date")
def copy_from_template(self):
def copy_from_template(self): # nosemgrep
"""
Copy tasks from template
"""
@@ -205,7 +205,7 @@ class Project(Document):
self.db_update()
def after_insert(self):
self.copy_from_template()
self.copy_from_template() # nosemgrep
if self.sales_order:
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
@@ -324,9 +324,13 @@ class Project(Document):
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
def update_billed_amount(self):
# nosemgrep
total_billed_amount = frappe.db.sql(
"""select sum(base_net_total)
from `tabSales Invoice` where project = %s and docstatus=1""",
"""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""",
self.name,
)
@@ -676,31 +680,8 @@ def update_project_sales_billing():
return
# Else simply fallback to Daily
exists_query = "(SELECT 1 from `tab{doctype}` where docstatus = 1 and project = `tabProject`.name)"
project_map = {}
for project_details in frappe.db.sql(
"""
SELECT name, 1 as order_exists, null as invoice_exists from `tabProject` where
exists {order_exists}
union
SELECT name, null as order_exists, 1 as invoice_exists from `tabProject` where
exists {invoice_exists}
""".format(
order_exists=exists_query.format(doctype="Sales Order"),
invoice_exists=exists_query.format(doctype="Sales Invoice"),
),
as_dict=True,
):
project = project_map.setdefault(
project_details.name, frappe.get_doc("Project", project_details.name)
)
if project_details.order_exists:
project.update_sales_amount()
if project_details.invoice_exists:
project.update_billed_amount()
for project in project_map.values():
project.save()
for project in frappe.get_all("Project", filters={"status": ["!=", "Cancelled"]}):
frappe.get_doc("Project", project.name).save()
@frappe.whitelist()
@@ -751,7 +732,6 @@ def get_users_email(doc):
def calculate_total_purchase_cost(project: str | None = None):
if project:
pitem = qb.DocType("Purchase Invoice Item")
frappe.qb.DocType("Purchase Invoice Item")
total_purchase_cost = (
qb.from_(pitem)
.select(Sum(pitem.base_net_amount))