fix: create default manager dashboard if not exists

(cherry picked from commit 05b8cea2066e27a8dbcf14aa5a8ae402f13e2130)
This commit is contained in:
Shariq Ansari 2025-07-14 18:50:58 +05:30 committed by Mergify
parent ba4ffdac86
commit 6f71d738b3
3 changed files with 34 additions and 15 deletions

View File

@ -3,6 +3,7 @@ import json
import frappe
from frappe import _
from crm.fcrm.doctype.crm_dashboard.crm_dashboard import create_default_manager_dashboard
from crm.utils import sales_user_only
@ -22,9 +23,15 @@ def get_dashboard(from_date="", to_date="", user=""):
if is_sales_user and not user:
user = frappe.session.user
dashboard = frappe.get_cached_doc("CRM Dashboard", "Manager Dashboard", fields=["layout"])
dashboard = frappe.db.exists("CRM Dashboard", "Manager Dashboard")
layout = json.loads(dashboard.layout) if dashboard and dashboard.layout else []
layout = []
if not dashboard:
layout = json.loads(create_default_manager_dashboard())
frappe.db.commit()
else:
layout = json.loads(frappe.db.get_value("CRM Dashboard", "Manager Dashboard", "layout") or "[]")
for l in layout:
method_name = f"get_{l['name']}"
@ -652,7 +659,7 @@ def get_forecasted_revenue(from_date="", to_date="", user=""):
return {
"data": result or [],
"title": _("Forecasted Revenue"),
"title": _("Forecasted revenue"),
"subtitle": _("Projected vs actual revenue based on deal probability"),
"xAxis": {
"title": _("Month"),
@ -714,7 +721,7 @@ def get_funnel_conversion(from_date="", to_date="", user=""):
return {
"data": result or [],
"title": _("Funnel Conversion"),
"title": _("Funnel conversion"),
"subtitle": _("Lead to deal conversion pipeline"),
"xAxis": {
"title": _("Stage"),

View File

@ -1,9 +1,29 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
import frappe
from frappe import _
from frappe.model.document import Document
class CRMDashboard(Document):
pass
def default_manager_dashboard_layout():
"""
Returns the default layout for the CRM Manager Dashboard.
"""
return '[{"name": "total_leads", "type": "number_chart", "tooltip": "Total number of leads", "layout": {"x": 0, "y": 0, "w": 4, "h": 2, "i": "total_leads"}}, {"name": "ongoing_deals", "type": "number_chart", "tooltip": "Total number of ongoing deals", "layout": {"x": 4, "y": 0, "w": 4, "h": 2, "i": "ongoing_deals"}}, {"name": "average_ongoing_deal_value", "type": "number_chart", "tooltip": "Average value of ongoing deals", "layout": {"x": 8, "y": 0, "w": 4, "h": 2, "i": "average_ongoing_deal_value"}}, {"name": "won_deals", "type": "number_chart", "tooltip": "Total number of won deals", "layout": {"x": 12, "y": 0, "w": 4, "h": 2, "i": "won_deals"}}, {"name": "average_won_deal_value", "type": "number_chart", "tooltip": "Average value of won deals", "layout": {"x": 16, "y": 0, "w": 4, "h": 2, "i": "average_won_deal_value"}}, {"name": "average_deal_value", "type": "number_chart", "tooltip": "Average deal value of ongoing and won deals", "layout": {"x": 0, "y": 2, "w": 4, "h": 2, "i": "average_deal_value"}}, {"name": "average_time_to_close_a_lead", "type": "number_chart", "tooltip": "Average time taken to close a lead", "layout": {"x": 4, "y": 2, "w": 4, "h": 2, "i": "average_time_to_close_a_lead"}}, {"name": "average_time_to_close_a_deal", "type": "number_chart", "layout": {"x": 8, "y": 2, "w": 4, "h": 2, "i": "average_time_to_close_a_deal"}}, {"name": "blank_card", "type": "blank_card", "layout": {"x": 12, "y": 2, "w": 8, "h": 2, "i": "blank_card"}}, {"name": "sales_trend", "type": "axis_chart", "layout": {"x": 0, "y": 4, "w": 10, "h": 7, "i": "sales_trend"}}, {"name": "forecasted_revenue", "type": "axis_chart", "layout": {"x": 10, "y": 4, "w": 10, "h": 7, "i": "forecasted_revenue"}}, {"name": "funnel_conversion", "type": "axis_chart", "layout": {"x": 0, "y": 11, "w": 10, "h": 7, "i": "funnel_conversion"}}, {"name": "deals_by_stage_axis", "type": "axis_chart", "layout": {"x": 10, "y": 11, "w": 10, "h": 7, "i": "deals_by_stage_axis"}}, {"name": "deals_by_stage_donut", "type": "donut_chart", "layout": {"x": 0, "y": 18, "w": 10, "h": 7, "i": "deals_by_stage_donut"}}, {"name": "lost_deal_reasons", "type": "axis_chart", "layout": {"x": 10, "y": 18, "w": 10, "h": 7, "i": "lost_deal_reasons"}}, {"name": "leads_by_source", "type": "donut_chart", "layout": {"x": 0, "y": 25, "w": 10, "h": 7, "i": "leads_by_source"}}, {"name": "deals_by_source", "type": "donut_chart", "layout": {"x": 10, "y": 25, "w": 10, "h": 7, "i": "deals_by_source"}}, {"name": "deals_by_territory", "type": "axis_chart", "layout": {"x": 0, "y": 32, "w": 10, "h": 7, "i": "deals_by_territory"}}, {"name": "deals_by_salesperson", "type": "axis_chart", "layout": {"x": 10, "y": 32, "w": 10, "h": 7, "i": "deals_by_salesperson"}}]'
def create_default_manager_dashboard():
"""
Creates the default CRM Manager Dashboard if it does not exist.
"""
if not frappe.db.exists("CRM Dashboard", "Manager Dashboard"):
doc = frappe.new_doc("CRM Dashboard")
doc.title = "Manager Dashboard"
doc.layout = default_manager_dashboard_layout()
doc.insert(ignore_permissions=True)
return doc.layout

View File

@ -4,6 +4,7 @@ import click
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from crm.fcrm.doctype.crm_dashboard.crm_dashboard import create_default_manager_dashboard
from crm.fcrm.doctype.crm_products.crm_products import create_product_details_script
@ -23,7 +24,7 @@ def after_install(force=False):
add_default_lost_reasons()
add_standard_dropdown_items()
add_default_scripts()
add_default_manager_dashboard()
create_default_manager_dashboard()
frappe.db.commit()
@ -420,12 +421,3 @@ def add_default_scripts():
for doctype in ["CRM Lead", "CRM Deal"]:
create_product_details_script(doctype)
create_forecasting_script()
def add_default_manager_dashboard():
if frappe.db.exists("CRM Dashboard", "Manager Dashboard"):
return
doc = frappe.new_doc("CRM Dashboard")
doc.title = "Manager Dashboard"
doc.layout = '[{"name": "total_leads", "type": "number_chart", "tooltip": "Total number of leads", "layout": {"x": 0, "y": 0, "w": 4, "h": 2, "i": "total_leads"}}, {"name": "ongoing_deals", "type": "number_chart", "tooltip": "Total number of ongoing deals", "layout": {"x": 4, "y": 0, "w": 4, "h": 2, "i": "ongoing_deals"}}, {"name": "average_ongoing_deal_value", "type": "number_chart", "tooltip": "Average value of ongoing deals", "layout": {"x": 8, "y": 0, "w": 4, "h": 2, "i": "average_ongoing_deal_value"}}, {"name": "won_deals", "type": "number_chart", "tooltip": "Total number of won deals", "layout": {"x": 12, "y": 0, "w": 4, "h": 2, "i": "won_deals"}}, {"name": "average_won_deal_value", "type": "number_chart", "tooltip": "Average value of won deals", "layout": {"x": 16, "y": 0, "w": 4, "h": 2, "i": "average_won_deal_value"}}, {"name": "average_deal_value", "type": "number_chart", "tooltip": "Average deal value of ongoing and won deals", "layout": {"x": 0, "y": 2, "w": 4, "h": 2, "i": "average_deal_value"}}, {"name": "average_time_to_close_a_lead", "type": "number_chart", "tooltip": "Average time taken to close a lead", "layout": {"x": 4, "y": 2, "w": 4, "h": 2, "i": "average_time_to_close_a_lead"}}, {"name": "average_time_to_close_a_deal", "type": "number_chart", "layout": {"x": 8, "y": 2, "w": 4, "h": 2, "i": "average_time_to_close_a_deal"}}, {"name": "blank_card", "type": "blank_card", "layout": {"x": 12, "y": 2, "w": 8, "h": 2, "i": "blank_card"}}, {"name": "sales_trend", "type": "axis_chart", "layout": {"x": 0, "y": 4, "w": 10, "h": 7, "i": "sales_trend"}}, {"name": "forecasted_revenue", "type": "axis_chart", "layout": {"x": 10, "y": 4, "w": 10, "h": 7, "i": "forecasted_revenue"}}, {"name": "funnel_conversion", "type": "axis_chart", "layout": {"x": 0, "y": 11, "w": 10, "h": 7, "i": "funnel_conversion"}}, {"name": "deals_by_stage_axis", "type": "axis_chart", "layout": {"x": 10, "y": 11, "w": 10, "h": 7, "i": "deals_by_stage_axis"}}, {"name": "deals_by_stage_donut", "type": "donut_chart", "layout": {"x": 0, "y": 18, "w": 10, "h": 7, "i": "deals_by_stage_donut"}}, {"name": "lost_deal_reasons", "type": "axis_chart", "layout": {"x": 10, "y": 18, "w": 10, "h": 7, "i": "lost_deal_reasons"}}, {"name": "leads_by_source", "type": "donut_chart", "layout": {"x": 0, "y": 25, "w": 10, "h": 7, "i": "leads_by_source"}}, {"name": "deals_by_source", "type": "donut_chart", "layout": {"x": 10, "y": 25, "w": 10, "h": 7, "i": "deals_by_source"}}, {"name": "deals_by_territory", "type": "axis_chart", "layout": {"x": 0, "y": 32, "w": 10, "h": 7, "i": "deals_by_territory"}}, {"name": "deals_by_salesperson", "type": "axis_chart", "layout": {"x": 10, "y": 32, "w": 10, "h": 7, "i": "deals_by_salesperson"}}]'