Merge pull request #22844 from anupamvs/crm-reports
refactor: Crm reports cleanup
diff --git a/erpnext/crm/report/lead_details/lead_details.js b/erpnext/crm/report/lead_details/lead_details.js
new file mode 100644
index 0000000..f92070d
--- /dev/null
+++ b/erpnext/crm/report/lead_details/lead_details.js
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Lead Details"] = {
+ "filters": [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -12),
+ "reqd": 1
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today(),
+ "reqd": 1
+ },
+ {
+ "fieldname":"status",
+ "label": __("Status"),
+ "fieldtype": "Select",
+ options: [
+ { "value": "Lead", "label": __("Lead") },
+ { "value": "Open", "label": __("Open") },
+ { "value": "Replied", "label": __("Replied") },
+ { "value": "Opportunity", "label": __("Opportunity") },
+ { "value": "Quotation", "label": __("Quotation") },
+ { "value": "Lost Quotation", "label": __("Lost Quotation") },
+ { "value": "Interested", "label": __("Interested") },
+ { "value": "Converted", "label": __("Converted") },
+ { "value": "Do Not Contact", "label": __("Do Not Contact") },
+ ],
+ },
+ {
+ "fieldname":"territory",
+ "label": __("Territory"),
+ "fieldtype": "Link",
+ "options": "Territory",
+ }
+ ]
+};
\ No newline at end of file
diff --git a/erpnext/crm/report/lead_details/lead_details.json b/erpnext/crm/report/lead_details/lead_details.json
index cdeb6bb..7871d08 100644
--- a/erpnext/crm/report/lead_details/lead_details.json
+++ b/erpnext/crm/report/lead_details/lead_details.json
@@ -7,16 +7,15 @@
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
- "modified": "2020-01-22 16:51:56.591110",
+ "modified": "2020-07-26 23:59:49.897577",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead Details",
"owner": "Administrator",
"prepared_report": 0,
- "query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name \n\t\tand `tabDynamic Link`.parenttype = 'Address'\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
"ref_doctype": "Lead",
"report_name": "Lead Details",
- "report_type": "Query Report",
+ "report_type": "Script Report",
"roles": [
{
"role": "Sales User"
diff --git a/erpnext/crm/report/lead_details/lead_details.py b/erpnext/crm/report/lead_details/lead_details.py
new file mode 100644
index 0000000..eeaaec2
--- /dev/null
+++ b/erpnext/crm/report/lead_details/lead_details.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe import _
+import frappe
+
+def execute(filters=None):
+ columns, data = get_columns(), get_data(filters)
+ return columns, data
+
+def get_columns():
+ columns = [
+ {
+ "label": _("Lead"),
+ "fieldname": "name",
+ "fieldtype": "Link",
+ "options": "Lead",
+ "width": 150,
+ },
+ {
+ "label": _("Lead Name"),
+ "fieldname": "lead_name",
+ "fieldtype": "Data",
+ "width": 120
+ },
+ {
+ "fieldname":"status",
+ "label": _("Status"),
+ "fieldtype": "Data",
+ "width": 100
+ },
+ {
+ "fieldname":"lead_owner",
+ "label": _("Lead Owner"),
+ "fieldtype": "Link",
+ "options": "User",
+ "width": 100
+ },
+ {
+ "label": _("Territory"),
+ "fieldname": "territory",
+ "fieldtype": "Link",
+ "options": "Territory",
+ "width": 100
+ },
+ {
+ "label": _("Source"),
+ "fieldname": "source",
+ "fieldtype": "Data",
+ "width": 120
+ },
+ {
+ "label": _("Email"),
+ "fieldname": "email_id",
+ "fieldtype": "Data",
+ "width": 120
+ },
+ {
+ "label": _("Mobile"),
+ "fieldname": "mobile_no",
+ "fieldtype": "Data",
+ "width": 120
+ },
+ {
+ "label": _("Phone"),
+ "fieldname": "phone",
+ "fieldtype": "Data",
+ "width": 120
+ },
+ {
+ "label": _("Owner"),
+ "fieldname": "owner",
+ "fieldtype": "Link",
+ "options": "user",
+ "width": 120
+ },
+ {
+ "label": _("Company"),
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "options": "Company",
+ "width": 120
+ },
+ {
+ "fieldname":"address",
+ "label": _("Address"),
+ "fieldtype": "Data",
+ "width": 130
+ },
+ {
+ "fieldname":"state",
+ "label": _("State"),
+ "fieldtype": "Data",
+ "width": 100
+ },
+ {
+ "fieldname":"pincode",
+ "label": _("Postal Code"),
+ "fieldtype": "Data",
+ "width": 90
+ },
+ {
+ "fieldname":"country",
+ "label": _("Country"),
+ "fieldtype": "Link",
+ "options": "Country",
+ "width": 100
+ },
+
+ ]
+ return columns
+
+def get_data(filters):
+ return frappe.db.sql("""
+ SELECT
+ `tabLead`.name,
+ `tabLead`.lead_name,
+ `tabLead`.status,
+ `tabLead`.lead_owner,
+ `tabLead`.territory,
+ `tabLead`.source,
+ `tabLead`.email_id,
+ `tabLead`.mobile_no,
+ `tabLead`.phone,
+ `tabLead`.owner,
+ `tabLead`.company,
+ concat_ws(', ',
+ trim(',' from `tabAddress`.address_line1),
+ trim(',' from tabAddress.address_line2)
+ ) AS address,
+ `tabAddress`.state,
+ `tabAddress`.pincode,
+ `tabAddress`.country
+ FROM
+ `tabLead` left join `tabDynamic Link` on (
+ `tabLead`.name = `tabDynamic Link`.link_name and
+ `tabDynamic Link`.parenttype = 'Address')
+ left join `tabAddress` on (
+ `tabAddress`.name=`tabDynamic Link`.parent)
+ WHERE
+ company = %(company)s
+ AND `tabLead`.creation BETWEEN %(from_date)s AND %(to_date)s
+ {conditions}
+ ORDER BY
+ `tabLead`.creation asc """.format(conditions=get_conditions(filters)), filters, as_dict=1)
+
+def get_conditions(filters) :
+ conditions = []
+
+ if filters.get("territory"):
+ conditions.append(" and `tabLead`.territory=%(territory)s")
+
+ if filters.get("status"):
+ conditions.append(" and `tabLead`.status=%(status)s")
+
+ return " ".join(conditions) if conditions else ""
+
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.js b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
new file mode 100644
index 0000000..d79f8c8
--- /dev/null
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
@@ -0,0 +1,67 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Lost Opportunity"] = {
+ "filters": [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -12),
+ "reqd": 1
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today(),
+ "reqd": 1
+ },
+ {
+ "fieldname":"lost_reason",
+ "label": __("Lost Reason"),
+ "fieldtype": "Link",
+ "options": "Opportunity Lost Reason"
+ },
+ {
+ "fieldname":"territory",
+ "label": __("Territory"),
+ "fieldtype": "Link",
+ "options": "Territory"
+ },
+ {
+ "fieldname":"opportunity_from",
+ "label": __("Opportunity From"),
+ "fieldtype": "Link",
+ "options": "DocType",
+ "get_query": function() {
+ return {
+ "filters": {
+ "name": ["in", ["Customer", "Lead"]],
+ }
+ }
+ }
+ },
+ {
+ "fieldname":"party_name",
+ "label": __("Party"),
+ "fieldtype": "Dynamic Link",
+ "options": "opportunity_from"
+ },
+ {
+ "fieldname":"contact_by",
+ "label": __("Next Contact By"),
+ "fieldtype": "Link",
+ "options": "User"
+ },
+ ]
+};
\ No newline at end of file
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.json b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
index e7c5068..e7a8e12 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.json
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
@@ -1,13 +1,14 @@
{
"add_total_row": 0,
"creation": "2018-12-31 16:30:57.188837",
+ "disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"json": "{\"order_by\": \"`tabOpportunity`.`modified` desc\", \"filters\": [[\"Opportunity\", \"status\", \"=\", \"Lost\"]], \"fields\": [[\"name\", \"Opportunity\"], [\"opportunity_from\", \"Opportunity\"], [\"party_name\", \"Opportunity\"], [\"customer_name\", \"Opportunity\"], [\"opportunity_type\", \"Opportunity\"], [\"status\", \"Opportunity\"], [\"contact_by\", \"Opportunity\"], [\"docstatus\", \"Opportunity\"], [\"lost_reason\", \"Lost Reason Detail\"]], \"add_totals_row\": 0, \"add_total_row\": 0, \"page_length\": 20}",
- "modified": "2019-06-26 16:33:08.083618",
+ "modified": "2020-07-29 15:49:02.848845",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lost Opportunity",
@@ -15,7 +16,7 @@
"prepared_report": 0,
"ref_doctype": "Opportunity",
"report_name": "Lost Opportunity",
- "report_type": "Report Builder",
+ "report_type": "Script Report",
"roles": [
{
"role": "Sales User"
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.py b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
new file mode 100644
index 0000000..1aa4afe
--- /dev/null
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
@@ -0,0 +1,131 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe import _
+import frappe
+
+def execute(filters=None):
+ columns, data = get_columns(), get_data(filters)
+ return columns, data
+
+def get_columns():
+ columns = [
+ {
+ "label": _("Opportunity"),
+ "fieldname": "name",
+ "fieldtype": "Link",
+ "options": "Opportunity",
+ "width": 170,
+ },
+ {
+ "label": _("Opportunity From"),
+ "fieldname": "opportunity_from",
+ "fieldtype": "Link",
+ "options": "DocType",
+ "width": 130
+ },
+ {
+ "label": _("Party"),
+ "fieldname":"party_name",
+ "fieldtype": "Dynamic Link",
+ "options": "opportunity_from",
+ "width": 160
+ },
+ {
+ "label": _("Customer/Lead Name"),
+ "fieldname":"customer_name",
+ "fieldtype": "Data",
+ "width": 150
+ },
+ {
+ "label": _("Opportunity Type"),
+ "fieldname": "opportunity_type",
+ "fieldtype": "Data",
+ "width": 130
+ },
+ {
+ "label": _("Lost Reasons"),
+ "fieldname": "lost_reason",
+ "fieldtype": "Data",
+ "width": 220
+ },
+ {
+ "label": _("Sales Stage"),
+ "fieldname": "sales_stage",
+ "fieldtype": "Link",
+ "options": "Sales Stage",
+ "width": 150
+ },
+ {
+ "label": _("Territory"),
+ "fieldname": "territory",
+ "fieldtype": "Link",
+ "options": "Territory",
+ "width": 150
+ },
+ {
+ "label": _("Next Contact By"),
+ "fieldname": "contact_by",
+ "fieldtype": "Link",
+ "options": "User",
+ "width": 150
+ }
+ ]
+ return columns
+
+def get_data(filters):
+ return frappe.db.sql("""
+ SELECT
+ `tabOpportunity`.name,
+ `tabOpportunity`.opportunity_from,
+ `tabOpportunity`.party_name,
+ `tabOpportunity`.customer_name,
+ `tabOpportunity`.opportunity_type,
+ `tabOpportunity`.contact_by,
+ GROUP_CONCAT(`tabOpportunity Lost Reason Detail`.lost_reason separator ', ') lost_reason,
+ `tabOpportunity`.sales_stage,
+ `tabOpportunity`.territory
+ FROM
+ `tabOpportunity`
+ {join}
+ WHERE
+ `tabOpportunity`.status = 'Lost' and `tabOpportunity`.company = %(company)s
+ AND `tabOpportunity`.modified BETWEEN %(from_date)s AND %(to_date)s
+ {conditions}
+ GROUP BY
+ `tabOpportunity`.name
+ ORDER BY
+ `tabOpportunity`.creation asc """.format(conditions=get_conditions(filters), join=get_join(filters)), filters, as_dict=1)
+
+
+def get_conditions(filters):
+ conditions = []
+
+ if filters.get("territory"):
+ conditions.append(" and `tabOpportunity`.territory=%(territory)s")
+
+ if filters.get("opportunity_from"):
+ conditions.append(" and `tabOpportunity`.opportunity_from=%(opportunity_from)s")
+
+ if filters.get("party_name"):
+ conditions.append(" and `tabOpportunity`.party_name=%(party_name)s")
+
+ if filters.get("contact_by"):
+ conditions.append(" and `tabOpportunity`.contact_by=%(contact_by)s")
+
+ 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"):
+ join = """JOIN `tabOpportunity Lost Reason Detail`
+ ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and
+ `tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name and
+ `tabOpportunity Lost Reason Detail`.lost_reason = '{0}'
+ """.format(filters.get("lost_reason"))
+
+ return join
\ No newline at end of file