diff --git a/crm/api/dashboard.py b/crm/api/dashboard.py index 4bed4218..0b51b6a2 100644 --- a/crm/api/dashboard.py +++ b/crm/api/dashboard.py @@ -1008,7 +1008,7 @@ def get_deals_by_territory(from_date="", to_date="", user=""): WHERE DATE(d.creation) BETWEEN %(from)s AND %(to)s {deal_conds} GROUP BY d.territory - ORDER BY value DESC + ORDER BY deals DESC, value DESC """, {"from": from_date, "to": to_date}, as_dict=True, @@ -1065,7 +1065,7 @@ def get_deals_by_salesperson(from_date="", to_date="", user=""): WHERE DATE(d.creation) BETWEEN %(from)s AND %(to)s {deal_conds} GROUP BY d.deal_owner - ORDER BY value DESC + ORDER BY deals DESC, value DESC """, {"from": from_date, "to": to_date}, as_dict=True, diff --git a/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py b/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py index 84351670..fde6fb72 100644 --- a/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py +++ b/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py @@ -135,7 +135,7 @@ def get_quotation_url(crm_deal, organization): "party_name": crm_deal, "company": erpnext_crm_settings.erpnext_company, "contact_person": contact, - "customer_address": address + "customer_address": address, } else: site_url = erpnext_crm_settings.get("erpnext_site_url") @@ -147,14 +147,11 @@ def get_quotation_url(crm_deal, organization): "party_name": prospect, "company": erpnext_crm_settings.erpnext_company, "contact_person": contact, - "customer_address": address + "customer_address": address, } - + # Filter out None values and build query string - query_string = "&".join( - f"{key}={value}" for key, value in params.items() - if value is not None - ) + query_string = "&".join(f"{key}={value}" for key, value in params.items() if value is not None) return f"{base_url}?{query_string}" diff --git a/crm/fcrm/doctype/helpdesk_crm_settings/__init__.py b/crm/fcrm/doctype/helpdesk_crm_settings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.js b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.js new file mode 100644 index 00000000..b31a6f24 --- /dev/null +++ b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.js @@ -0,0 +1,8 @@ +// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Helpdesk CRM Settings", { +// refresh(frm) { + +// }, +// }); diff --git a/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.json b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.json new file mode 100644 index 00000000..220666ab --- /dev/null +++ b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.json @@ -0,0 +1,102 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2025-08-18 17:25:49.638398", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "enabled", + "column_break_idaw", + "is_helpdesk_in_different_site", + "helpdesk_site_url", + "helpdesk_site_apis_section", + "api_key", + "column_break_tqsm", + "api_secret" + ], + "fields": [ + { + "default": "0", + "fieldname": "enabled", + "fieldtype": "Check", + "label": "Enabled" + }, + { + "fieldname": "column_break_idaw", + "fieldtype": "Column Break" + }, + { + "default": "0", + "depends_on": "enabled", + "fieldname": "is_helpdesk_in_different_site", + "fieldtype": "Check", + "label": "Is Helpdesk installed on a different site?" + }, + { + "depends_on": "eval:doc.enabled && doc.is_helpdesk_in_different_site", + "fieldname": "helpdesk_site_url", + "fieldtype": "Data", + "label": "Helpdesk Site URL", + "mandatory_depends_on": "is_helpdesk_in_different_site" + }, + { + "depends_on": "enabled", + "fieldname": "helpdesk_site_apis_section", + "fieldtype": "Section Break", + "label": "Helpdesk Site API's" + }, + { + "depends_on": "eval:doc.enabled && doc.is_helpdesk_in_different_site", + "fieldname": "api_key", + "fieldtype": "Data", + "label": "API Key", + "mandatory_depends_on": "is_helpdesk_in_different_site" + }, + { + "fieldname": "column_break_tqsm", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval:doc.enabled && doc.is_helpdesk_in_different_site", + "fieldname": "api_secret", + "fieldtype": "Password", + "label": "API Secret", + "mandatory_depends_on": "is_helpdesk_in_different_site" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2025-08-18 17:33:38.616328", + "modified_by": "Administrator", + "module": "FCRM", + "name": "Helpdesk CRM Settings", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "Sales Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} diff --git a/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.py b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.py new file mode 100644 index 00000000..efc6b999 --- /dev/null +++ b/crm/fcrm/doctype/helpdesk_crm_settings/helpdesk_crm_settings.py @@ -0,0 +1,178 @@ +# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document + + +class HelpdeskCRMSettings(Document): + def validate(self): + if self.enabled: + self.validate_if_helpdesk_installed() + self.create_helpdesk_script() + + def validate_if_helpdesk_installed(self): + if not self.is_helpdesk_in_different_site: + if "helpdesk" not in frappe.get_installed_apps(): + frappe.throw(_("Helpdesk is not installed in the current site")) + + def create_helpdesk_script(self): + if not frappe.db.exists("CRM Form Script", "Helpdesk Integration Script"): + script = get_helpdesk_script() + frappe.get_doc( + { + "doctype": "CRM Form Script", + "name": "Helpdesk Integration Script", + "dt": "CRM Deal", + "view": "Form", + "script": script, + "enabled": 1, + "is_standard": 1, + } + ).insert() + + +@frappe.whitelist() +def create_customer_in_helpdesk(name, email): + helpdesk_crm_settings = frappe.get_single("Helpdesk CRM Settings") + if not helpdesk_crm_settings.enabled: + frappe.throw(_("Helpdesk is not integrated with the CRM")) + + if not helpdesk_crm_settings.is_helpdesk_in_different_site: + # from helpdesk.integrations.crm.api import create_customer + return create_customer(name, email) + + +def get_helpdesk_script(): + return """class CRMDeal { + onLoad() { + this.actions.push( + { + group: "Helpdesk", + hideLabel: true, + items: [ + { + label: "Create customer in Helpdesk", + onClick: () => { + call('crm.fcrm.doctype.helpdesk_crm_settings.helpdesk_crm_settings.create_customer_in_helpdesk', { + name: this.doc.organization, + email: this.doc.email + }).then((a) => { + toast.success("Customer created successfully, " + a.customer) + }) + } + } + ] + } + ) + } +}""" + +# Helpdesk methods TODO: move to helpdesk.integrations.crm.api +def create_customer(name, email): + customer = frappe.db.exists("HD Customer", name) + if not customer: + customer = frappe.get_doc( + { + "doctype": "HD Customer", + "customer_name": name, + } + ) + customer.insert(ignore_permissions=True, ignore_if_duplicate=True) + else: + customer = frappe.get_doc("HD Customer", customer) + + contact = frappe.db.exists("Contact", {"email_id": email}) + if contact: + contact = frappe.get_doc("Contact", contact) + contact.append( + "links", {"link_doctype": "HD Customer", "link_name": customer.name} + ) + contact.save(ignore_permissions=True) + else: + contact = frappe.get_doc( + { + "doctype": "Contact", + "first_name": email.split("@")[0], + "email_ids": [{"email_id": email, "is_primary": 1}], + "links": [{"link_doctype": "HD Customer", "link_name": customer.name}], + } + ) + contact.insert(ignore_permissions=True) + + if not frappe.db.exists("User", contact.email_id): + invite_user(contact.name) + else: + base_url = frappe.utils.get_url() + "/helpdesk" + frappe.sendmail( + recipients=[contact.email_id], + subject="Welcome existing user to Helpdesk", + message=f""" +
+ {{_("Hello")}} {{ first_name }}{% if last_name %} {{ last_name}}{% endif %}, +
+{% set site_link = "" + site_url + "" %} +{{_("A new account has been created for you at {0}").format(site_link)}}.
+{{_("Your login id is")}}: {{ user }} +
{{_("Click on the link below to complete your registration and set a new password")}}.
+ ++ {{ _("Complete Registration") }} +
+ +{% if created_by != "Administrator" %} +
+ {{_("Thanks")}},
+ {{ created_by }}
+
+ {{_("You can also copy-paste following link in your browser")}}
+ {{ link }}
+