Merge pull request #567 from shariquerik/set-address-contact-in-quotation

This commit is contained in:
Shariq Ansari 2025-02-03 16:20:37 +05:30 committed by GitHub
commit 3b8655b69d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 66 additions and 40 deletions

View File

@ -1,22 +1,24 @@
# Copyright (c) 2024, Frappe and contributors # Copyright (c) 2024, Frappe and contributors
# For license information, please see license.txt # For license information, please see license.txt
import json
import frappe import frappe
from frappe import _ from frappe import _
from frappe.custom.doctype.property_setter.property_setter import make_property_setter 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.frappeclient import FrappeClient
from frappe.model.document import Document
from frappe.utils import get_url_to_form, get_url_to_list from frappe.utils import get_url_to_form, get_url_to_list
import json
class ERPNextCRMSettings(Document): class ERPNextCRMSettings(Document):
def validate(self): def validate(self):
if self.enabled: if self.enabled:
self.validate_if_erpnext_installed() self.validate_if_erpnext_installed()
self.add_quotation_to_option() self.add_quotation_to_option()
self.create_custom_fields() self.create_custom_fields()
self.create_crm_form_script() self.create_crm_form_script()
def validate_if_erpnext_installed(self): def validate_if_erpnext_installed(self):
if not self.is_erpnext_in_different_site: if not self.is_erpnext_in_different_site:
if "erpnext" not in frappe.get_installed_apps(): if "erpnext" not in frappe.get_installed_apps():
@ -37,6 +39,7 @@ class ERPNextCRMSettings(Document):
def create_custom_fields(self): def create_custom_fields(self):
if not self.is_erpnext_in_different_site: if not self.is_erpnext_in_different_site:
from erpnext.crm.frappe_crm_api import create_custom_fields_for_frappe_crm from erpnext.crm.frappe_crm_api import create_custom_fields_for_frappe_crm
create_custom_fields_for_frappe_crm() create_custom_fields_for_frappe_crm()
else: else:
self.create_custom_fields_in_remote_site() self.create_custom_fields_in_remote_site()
@ -48,22 +51,24 @@ class ERPNextCRMSettings(Document):
except Exception: except Exception:
frappe.log_error( frappe.log_error(
frappe.get_traceback(), 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") frappe.throw("Error while creating custom field in ERPNext, check error log for more details")
def create_crm_form_script(self): def create_crm_form_script(self):
if not frappe.db.exists("CRM Form Script", "Create Quotation from CRM Deal"): if not frappe.db.exists("CRM Form Script", "Create Quotation from CRM Deal"):
script = get_crm_form_script() script = get_crm_form_script()
frappe.get_doc({ frappe.get_doc(
"doctype": "CRM Form Script", {
"name": "Create Quotation from CRM Deal", "doctype": "CRM Form Script",
"dt": "CRM Deal", "name": "Create Quotation from CRM Deal",
"view": "Form", "dt": "CRM Deal",
"script": script, "view": "Form",
"enabled": 1, "script": script,
"is_standard": 1 "enabled": 1,
}).insert() "is_standard": 1,
}
).insert()
@frappe.whitelist() @frappe.whitelist()
def reset_erpnext_form_script(self): def reset_erpnext_form_script(self):
@ -77,14 +82,14 @@ class ERPNextCRMSettings(Document):
frappe.log_error(frappe.get_traceback(), "Error while resetting form script") frappe.log_error(frappe.get_traceback(), "Error while resetting form script")
return False return False
def get_erpnext_site_client(erpnext_crm_settings): def get_erpnext_site_client(erpnext_crm_settings):
site_url = erpnext_crm_settings.erpnext_site_url site_url = erpnext_crm_settings.erpnext_site_url
api_key = erpnext_crm_settings.api_key api_key = erpnext_crm_settings.api_key
api_secret = erpnext_crm_settings.get_password("api_secret", raise_exception=False) api_secret = erpnext_crm_settings.get_password("api_secret", raise_exception=False)
return FrappeClient( return FrappeClient(site_url, api_key=api_key, api_secret=api_secret)
site_url, api_key=api_key, api_secret=api_secret
)
@frappe.whitelist() @frappe.whitelist()
def get_customer_link(crm_deal): def get_customer_link(crm_deal):
@ -107,7 +112,7 @@ def get_customer_link(crm_deal):
except Exception: except Exception:
frappe.log_error( frappe.log_error(
frappe.get_traceback(), 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")) 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: if not erpnext_crm_settings.enabled:
frappe.throw(_("ERPNext is not integrated with the CRM")) 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: if not erpnext_crm_settings.is_erpnext_in_different_site:
quotation_url = get_url_to_list("Quotation") 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: else:
site_url = erpnext_crm_settings.get("erpnext_site_url") site_url = erpnext_crm_settings.get("erpnext_site_url")
quotation_url = f"{site_url}/app/quotation" quotation_url = f"{site_url}/app/quotation"
prospect = create_prospect_in_remote_site(crm_deal, erpnext_crm_settings) 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): def create_prospect_in_remote_site(crm_deal, erpnext_crm_settings):
try: try:
client = get_erpnext_site_client(erpnext_crm_settings) 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) contacts = get_contacts(doc)
address = get_organization_address(doc.organization) 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, "organization": doc.organization,
"lead_name": doc.lead_name, "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, "annual_revenue": doc.annual_revenue,
"contacts": json.dumps(contacts), "contacts": json.dumps(contacts),
"erpnext_company": erpnext_crm_settings.erpnext_company, "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: except Exception:
frappe.log_error( frappe.log_error(
frappe.get_traceback(), 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")) 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): def get_contacts(doc):
contacts = [] contacts = []
for c in doc.contacts: for c in doc.contacts:
contacts.append({ contacts.append(
"contact": c.contact, {
"full_name": c.full_name, "contact": c.contact,
"email": c.email, "full_name": c.full_name,
"mobile_no": c.mobile_no, "email": c.email,
"gender": c.gender, "mobile_no": c.mobile_no,
"is_primary": c.is_primary, "gender": c.gender,
}) "is_primary": c.is_primary,
}
)
return contacts return contacts
def get_organization_address(organization): def get_organization_address(organization):
address = frappe.db.get_value("CRM Organization", organization, "address") 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: if not address:
return None return None
return { return {
@ -188,6 +213,7 @@ def get_organization_address(organization):
"pincode": address.pincode, "pincode": address.pincode,
} }
def create_customer_in_erpnext(doc, method): def create_customer_in_erpnext(doc, method):
erpnext_crm_settings = frappe.get_single("ERPNext CRM Settings") erpnext_crm_settings = frappe.get_single("ERPNext CRM Settings")
if ( if (
@ -196,7 +222,7 @@ def create_customer_in_erpnext(doc, method):
or doc.status != erpnext_crm_settings.deal_status or doc.status != erpnext_crm_settings.deal_status
): ):
return return
contacts = get_contacts(doc) contacts = get_contacts(doc)
address = get_organization_address(doc.organization) address = get_organization_address(doc.organization)
customer = { customer = {
@ -213,26 +239,26 @@ def create_customer_in_erpnext(doc, method):
} }
if not erpnext_crm_settings.is_erpnext_in_different_site: if not erpnext_crm_settings.is_erpnext_in_different_site:
from erpnext.crm.frappe_crm_api import create_customer from erpnext.crm.frappe_crm_api import create_customer
create_customer(customer) create_customer(customer)
else: else:
create_customer_in_remote_site(customer, erpnext_crm_settings) create_customer_in_remote_site(customer, erpnext_crm_settings)
frappe.publish_realtime("crm_customer_created") frappe.publish_realtime("crm_customer_created")
def create_customer_in_remote_site(customer, erpnext_crm_settings): def create_customer_in_remote_site(customer, erpnext_crm_settings):
client = get_erpnext_site_client(erpnext_crm_settings) client = get_erpnext_site_client(erpnext_crm_settings)
try: try:
client.post_api("erpnext.crm.frappe_crm_api.create_customer", customer) client.post_api("erpnext.crm.frappe_crm_api.create_customer", customer)
except Exception: except Exception:
frappe.log_error( frappe.log_error(frappe.get_traceback(), "Error while creating customer in remote site")
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.throw(_("Error while creating customer in ERPNext, check error log for more details"))
@frappe.whitelist() @frappe.whitelist()
def get_crm_form_script(): def get_crm_form_script():
return """ return """
async function setupForm({ doc, call, $dialog, updateField, createToast }) { async function setupForm({ doc, call, $dialog, updateField, createToast }) {
let actions = []; let actions = [];
let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"}); let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"});

View File

@ -216,7 +216,7 @@ async function startCamera() {
} }
function stopStream() { function stopStream() {
stream.value.getTracks().forEach((track) => track.stop()) stream.value?.getTracks()?.forEach((track) => track.stop())
showCamera.value = false showCamera.value = false
cameraImage.value = null cameraImage.value = null
} }