refactor(lost_opportunity_report): replaced raw_sql with query builder (backport #54136) (#54140)

Co-authored-by: diptanilsaha <diptanil@frappe.io>
This commit is contained in:
mergify[bot]
2026-04-08 18:30:35 +00:00
committed by GitHub
parent 7b0d34e979
commit 526c8d0418

View File

@@ -4,6 +4,12 @@
import frappe import frappe
from frappe import _ from frappe import _
from frappe.query_builder import DocType
from frappe.query_builder.custom import GROUP_CONCAT
from frappe.query_builder.functions import Date
Opportunity = DocType("Opportunity")
OpportunityLostReasonDetail = DocType("Opportunity Lost Reason Detail")
def execute(filters=None): def execute(filters=None):
@@ -66,58 +72,48 @@ def get_columns():
def get_data(filters): def get_data(filters):
return frappe.db.sql( query = (
f""" frappe.qb.from_(Opportunity)
SELECT .left_join(OpportunityLostReasonDetail)
`tabOpportunity`.name, .on(
`tabOpportunity`.opportunity_from, (OpportunityLostReasonDetail.parenttype == "Opportunity")
`tabOpportunity`.party_name, & (OpportunityLostReasonDetail.parent == Opportunity.name)
`tabOpportunity`.customer_name, )
`tabOpportunity`.opportunity_type, .select(
GROUP_CONCAT(`tabOpportunity Lost Reason Detail`.lost_reason separator ', ') lost_reason, Opportunity.name,
`tabOpportunity`.sales_stage, Opportunity.opportunity_from,
`tabOpportunity`.territory Opportunity.party_name,
FROM Opportunity.customer_name,
`tabOpportunity` Opportunity.opportunity_type,
{get_join(filters)} GROUP_CONCAT(OpportunityLostReasonDetail.lost_reason, alias="lost_reason").separator(", "),
WHERE Opportunity.sales_stage,
`tabOpportunity`.status = 'Lost' and `tabOpportunity`.company = %(company)s Opportunity.territory,
AND DATE(`tabOpportunity`.modified) BETWEEN %(from_date)s AND %(to_date)s )
{get_conditions(filters)} .where(
GROUP BY (Opportunity.status == "Lost")
`tabOpportunity`.name & (Opportunity.company == filters.get("company"))
ORDER BY & (Date(Opportunity.modified).between(filters.get("from_date"), filters.get("to_date")))
`tabOpportunity`.creation asc """, )
filters, .groupby(Opportunity.name)
as_dict=1, .orderby(Opportunity.creation)
) )
query = get_conditions(filters, query)
def get_conditions(filters): return query.run(as_dict=1)
conditions = []
def get_conditions(filters, query):
if filters.get("territory"): if filters.get("territory"):
conditions.append(" and `tabOpportunity`.territory=%(territory)s") query = query.where(Opportunity.territory == filters.get("territory"))
if filters.get("opportunity_from"): if filters.get("opportunity_from"):
conditions.append(" and `tabOpportunity`.opportunity_from=%(opportunity_from)s") query = query.where(Opportunity.opportunity_from == filters.get("opportunity_from"))
if filters.get("party_name"): if filters.get("party_name"):
conditions.append(" and `tabOpportunity`.party_name=%(party_name)s") query = query.where(Opportunity.party_name == filters.get("party_name"))
return " ".join(conditions) if conditions else ""
def get_join(filters):
join = """LEFT JOIN `tabOpportunity Lost Reason Detail`
ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and
`tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name"""
if filters.get("lost_reason"): if filters.get("lost_reason"):
join = """JOIN `tabOpportunity Lost Reason Detail` query = query.where(OpportunityLostReasonDetail.lost_reason == filters.get("lost_reason"))
ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and
`tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name and
`tabOpportunity Lost Reason Detail`.lost_reason = '{}'
""".format(filters.get("lost_reason"))
return join return query