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 2e15a011..1d63807e 100644 --- a/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py +++ b/crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py @@ -1,22 +1,24 @@ # Copyright (c) 2024, Frappe and contributors # For license information, please see license.txt +import json + import frappe from frappe import _ from frappe.custom.doctype.property_setter.property_setter import make_property_setter -from frappe.model.document import Document from frappe.frappeclient import FrappeClient +from frappe.model.document import Document from frappe.utils import get_url_to_form, get_url_to_list -import json + class ERPNextCRMSettings(Document): def validate(self): if self.enabled: self.validate_if_erpnext_installed() self.add_quotation_to_option() - self.create_custom_fields() + self.create_custom_fields() self.create_crm_form_script() - + def validate_if_erpnext_installed(self): if not self.is_erpnext_in_different_site: if "erpnext" not in frappe.get_installed_apps(): @@ -37,6 +39,7 @@ class ERPNextCRMSettings(Document): def create_custom_fields(self): if not self.is_erpnext_in_different_site: from erpnext.crm.frappe_crm_api import create_custom_fields_for_frappe_crm + create_custom_fields_for_frappe_crm() else: self.create_custom_fields_in_remote_site() @@ -48,22 +51,24 @@ class ERPNextCRMSettings(Document): except Exception: frappe.log_error( frappe.get_traceback(), - f"Error while creating custom field in the remote erpnext site: {self.erpnext_site_url}" + f"Error while creating custom field in the remote erpnext site: {self.erpnext_site_url}", ) frappe.throw("Error while creating custom field in ERPNext, check error log for more details") def create_crm_form_script(self): if not frappe.db.exists("CRM Form Script", "Create Quotation from CRM Deal"): script = get_crm_form_script() - frappe.get_doc({ - "doctype": "CRM Form Script", - "name": "Create Quotation from CRM Deal", - "dt": "CRM Deal", - "view": "Form", - "script": script, - "enabled": 1, - "is_standard": 1 - }).insert() + frappe.get_doc( + { + "doctype": "CRM Form Script", + "name": "Create Quotation from CRM Deal", + "dt": "CRM Deal", + "view": "Form", + "script": script, + "enabled": 1, + "is_standard": 1, + } + ).insert() @frappe.whitelist() def reset_erpnext_form_script(self): @@ -77,14 +82,14 @@ class ERPNextCRMSettings(Document): frappe.log_error(frappe.get_traceback(), "Error while resetting form script") return False + def get_erpnext_site_client(erpnext_crm_settings): site_url = erpnext_crm_settings.erpnext_site_url api_key = erpnext_crm_settings.api_key api_secret = erpnext_crm_settings.get_password("api_secret", raise_exception=False) - return FrappeClient( - site_url, api_key=api_key, api_secret=api_secret - ) + return FrappeClient(site_url, api_key=api_key, api_secret=api_secret) + @frappe.whitelist() def get_customer_link(crm_deal): @@ -107,7 +112,7 @@ def get_customer_link(crm_deal): except Exception: frappe.log_error( frappe.get_traceback(), - f"Error while fetching customer in remote site: {erpnext_crm_settings.erpnext_site_url}" + f"Error while fetching customer in remote site: {erpnext_crm_settings.erpnext_site_url}", ) frappe.throw(_("Error while fetching customer in ERPNext, check error log for more details")) @@ -118,23 +123,28 @@ def get_quotation_url(crm_deal, organization): if not erpnext_crm_settings.enabled: frappe.throw(_("ERPNext is not integrated with the CRM")) + contact = get_contact(crm_deal) + address = get_organization_address(organization).get("name") if organization else None + if not erpnext_crm_settings.is_erpnext_in_different_site: quotation_url = get_url_to_list("Quotation") - return f"{quotation_url}/new?quotation_to=CRM Deal&crm_deal={crm_deal}&party_name={crm_deal}&company={erpnext_crm_settings.erpnext_company}" + return f"{quotation_url}/new?quotation_to=CRM Deal&crm_deal={crm_deal}&party_name={crm_deal}&company={erpnext_crm_settings.erpnext_company}&contact_person={contact}&customer_address={address}" else: site_url = erpnext_crm_settings.get("erpnext_site_url") quotation_url = f"{site_url}/app/quotation" prospect = create_prospect_in_remote_site(crm_deal, erpnext_crm_settings) - return f"{quotation_url}/new?quotation_to=Prospect&crm_deal={crm_deal}&party_name={prospect}&company={erpnext_crm_settings.erpnext_company}" + return f"{quotation_url}/new?quotation_to=Prospect&crm_deal={crm_deal}&party_name={prospect}&company={erpnext_crm_settings.erpnext_company}&contact_person={contact}&customer_address={address}" + def create_prospect_in_remote_site(crm_deal, erpnext_crm_settings): try: client = get_erpnext_site_client(erpnext_crm_settings) - doc = frappe.get_doc("CRM Deal", crm_deal) + doc = frappe.get_cached_doc("CRM Deal", crm_deal) contacts = get_contacts(doc) address = get_organization_address(doc.organization) - return client.post_api("erpnext.crm.frappe_crm_api.create_prospect_against_crm_deal", + return client.post_api( + "erpnext.crm.frappe_crm_api.create_prospect_against_crm_deal", { "organization": doc.organization, "lead_name": doc.lead_name, @@ -147,32 +157,47 @@ def create_prospect_in_remote_site(crm_deal, erpnext_crm_settings): "annual_revenue": doc.annual_revenue, "contacts": json.dumps(contacts), "erpnext_company": erpnext_crm_settings.erpnext_company, - "address": address.as_dict() if address else None + "address": address.as_dict() if address else None, }, ) except Exception: frappe.log_error( frappe.get_traceback(), - f"Error while creating prospect in remote site: {erpnext_crm_settings.erpnext_site_url}" + f"Error while creating prospect in remote site: {erpnext_crm_settings.erpnext_site_url}", ) frappe.throw(_("Error while creating prospect in ERPNext, check error log for more details")) + +def get_contact(crm_deal): + doc = frappe.get_cached_doc("CRM Deal", crm_deal) + contact = None + for c in doc.contacts: + if c.is_primary: + contact = c.contact + break + + return contact + + def get_contacts(doc): contacts = [] for c in doc.contacts: - contacts.append({ - "contact": c.contact, - "full_name": c.full_name, - "email": c.email, - "mobile_no": c.mobile_no, - "gender": c.gender, - "is_primary": c.is_primary, - }) + contacts.append( + { + "contact": c.contact, + "full_name": c.full_name, + "email": c.email, + "mobile_no": c.mobile_no, + "gender": c.gender, + "is_primary": c.is_primary, + } + ) return contacts + def get_organization_address(organization): address = frappe.db.get_value("CRM Organization", organization, "address") - address = frappe.get_doc("Address", address) if address else None + address = frappe.get_cached_doc("Address", address) if address else None if not address: return None return { @@ -188,6 +213,7 @@ def get_organization_address(organization): "pincode": address.pincode, } + def create_customer_in_erpnext(doc, method): erpnext_crm_settings = frappe.get_single("ERPNext CRM Settings") if ( @@ -196,7 +222,7 @@ def create_customer_in_erpnext(doc, method): or doc.status != erpnext_crm_settings.deal_status ): return - + contacts = get_contacts(doc) address = get_organization_address(doc.organization) customer = { @@ -213,26 +239,26 @@ def create_customer_in_erpnext(doc, method): } if not erpnext_crm_settings.is_erpnext_in_different_site: from erpnext.crm.frappe_crm_api import create_customer + create_customer(customer) else: create_customer_in_remote_site(customer, erpnext_crm_settings) frappe.publish_realtime("crm_customer_created") + def create_customer_in_remote_site(customer, erpnext_crm_settings): client = get_erpnext_site_client(erpnext_crm_settings) try: client.post_api("erpnext.crm.frappe_crm_api.create_customer", customer) except Exception: - frappe.log_error( - frappe.get_traceback(), - "Error while creating customer in remote site" - ) + frappe.log_error(frappe.get_traceback(), "Error while creating customer in remote site") frappe.throw(_("Error while creating customer in ERPNext, check error log for more details")) + @frappe.whitelist() def get_crm_form_script(): - return """ + return """ async function setupForm({ doc, call, $dialog, updateField, createToast }) { let actions = []; let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"}); diff --git a/frontend/src/components/FilesUploader/FilesUploaderArea.vue b/frontend/src/components/FilesUploader/FilesUploaderArea.vue index 85689909..cf69c2fb 100644 --- a/frontend/src/components/FilesUploader/FilesUploaderArea.vue +++ b/frontend/src/components/FilesUploader/FilesUploaderArea.vue @@ -216,7 +216,7 @@ async function startCamera() { } function stopStream() { - stream.value.getTracks().forEach((track) => track.stop()) + stream.value?.getTracks()?.forEach((track) => track.stop()) showCamera.value = false cameraImage.value = null }