feat: de-duplicate leads
This commit is contained in:
parent
3ac4a582f5
commit
9cd86e99c3
@ -55,7 +55,9 @@
|
|||||||
"first_response_time",
|
"first_response_time",
|
||||||
"first_responded_on",
|
"first_responded_on",
|
||||||
"log_tab",
|
"log_tab",
|
||||||
"status_change_log"
|
"status_change_log",
|
||||||
|
"syncing_tab",
|
||||||
|
"facebook_lead_id"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -325,13 +327,24 @@
|
|||||||
"label": "Net Total",
|
"label": "Net Total",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "syncing_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Syncing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "facebook_lead_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Facebook Lead ID",
|
||||||
|
"unique": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-05-14 19:51:06.184569",
|
"modified": "2025-09-29 19:21:49.483883",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "FCRM",
|
"module": "FCRM",
|
||||||
"name": "CRM Lead",
|
"name": "CRM Lead",
|
||||||
|
|||||||
@ -14,6 +14,52 @@ from crm.fcrm.doctype.crm_status_change_log.crm_status_change_log import (
|
|||||||
|
|
||||||
|
|
||||||
class CRMLead(Document):
|
class CRMLead(Document):
|
||||||
|
# begin: auto-generated types
|
||||||
|
# This code is auto-generated. Do not modify anything in this block.
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from crm.fcrm.doctype.crm_products.crm_products import CRMProducts
|
||||||
|
from crm.fcrm.doctype.crm_status_change_log.crm_status_change_log import CRMStatusChangeLog
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
annual_revenue: DF.Currency
|
||||||
|
communication_status: DF.Link | None
|
||||||
|
converted: DF.Check
|
||||||
|
email: DF.Data | None
|
||||||
|
facebook_lead_id: DF.Data | None
|
||||||
|
first_name: DF.Data
|
||||||
|
first_responded_on: DF.Datetime | None
|
||||||
|
first_response_time: DF.Duration | None
|
||||||
|
gender: DF.Link | None
|
||||||
|
image: DF.AttachImage | None
|
||||||
|
industry: DF.Link | None
|
||||||
|
job_title: DF.Data | None
|
||||||
|
last_name: DF.Data | None
|
||||||
|
lead_name: DF.Data | None
|
||||||
|
lead_owner: DF.Link | None
|
||||||
|
middle_name: DF.Data | None
|
||||||
|
mobile_no: DF.Data | None
|
||||||
|
naming_series: DF.Literal["CRM-LEAD-.YYYY.-"]
|
||||||
|
net_total: DF.Currency
|
||||||
|
no_of_employees: DF.Literal["1-10", "11-50", "51-200", "201-500", "501-1000", "1000+"]
|
||||||
|
organization: DF.Data | None
|
||||||
|
phone: DF.Data | None
|
||||||
|
products: DF.Table[CRMProducts]
|
||||||
|
response_by: DF.Datetime | None
|
||||||
|
salutation: DF.Link | None
|
||||||
|
sla: DF.Link | None
|
||||||
|
sla_creation: DF.Datetime | None
|
||||||
|
sla_status: DF.Literal["", "First Response Due", "Failed", "Fulfilled"]
|
||||||
|
source: DF.Link | None
|
||||||
|
status: DF.Link
|
||||||
|
status_change_log: DF.Table[CRMStatusChangeLog]
|
||||||
|
territory: DF.Link | None
|
||||||
|
total: DF.Currency
|
||||||
|
website: DF.Data | None
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
def before_validate(self):
|
def before_validate(self):
|
||||||
self.set_sla()
|
self.set_sla()
|
||||||
|
|
||||||
|
|||||||
@ -58,14 +58,15 @@
|
|||||||
"fieldname": "facebook_lead_form",
|
"fieldname": "facebook_lead_form",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Facebook Lead Form",
|
"label": "Facebook Lead Form",
|
||||||
"options": "Facebook Lead Form"
|
"options": "Facebook Lead Form",
|
||||||
|
"unique": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-09-29 18:45:32.305860",
|
"modified": "2025-09-29 19:03:14.804026",
|
||||||
"modified_by": "hussain@frappe.io",
|
"modified_by": "Administrator",
|
||||||
"module": "Lead Syncing",
|
"module": "Lead Syncing",
|
||||||
"name": "Lead Sync Source",
|
"name": "Lead Sync Source",
|
||||||
"naming_rule": "Autoincrement",
|
"naming_rule": "Autoincrement",
|
||||||
|
|||||||
@ -46,6 +46,14 @@ class LeadSyncSource(Document):
|
|||||||
|
|
||||||
def sync_leads_from_facebook(access_token: str, lead_form_id: str) -> None:
|
def sync_leads_from_facebook(access_token: str, lead_form_id: str) -> None:
|
||||||
url = get_fb_graph_api_url(f"/{lead_form_id}/leads")
|
url = get_fb_graph_api_url(f"/{lead_form_id}/leads")
|
||||||
|
last_synced_at = frappe.db.get_value(
|
||||||
|
"Lead Sync Source", {"facebook_lead_form": lead_form_id}, "last_synced_at"
|
||||||
|
)
|
||||||
|
timestamp = frappe.utils.data.get_timestamp(last_synced_at)
|
||||||
|
filtering = f"filtering=[{{'field':'time_created','operator':'GREATER_THAN','value':{timestamp}}}]"
|
||||||
|
if last_synced_at:
|
||||||
|
url = f"{url}?{filtering}"
|
||||||
|
|
||||||
leads = make_get_request(
|
leads = make_get_request(
|
||||||
url,
|
url,
|
||||||
params={
|
params={
|
||||||
@ -60,24 +68,33 @@ def sync_leads_from_facebook(access_token: str, lead_form_id: str) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Map form questions to CRM Lead fields
|
# Map form questions to CRM Lead fields
|
||||||
question_to_field_map = {q["key"]: q["mapped_to_crm_field"]
|
question_to_field_map = {
|
||||||
for q in form_questions
|
q["key"]: q["mapped_to_crm_field"] for q in form_questions if q["mapped_to_crm_field"]
|
||||||
if q["mapped_to_crm_field"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for lead in leads:
|
for lead in leads:
|
||||||
lead_data = {item["name"]: item["values"][0] for item in lead["field_data"]}
|
lead_data = {item["name"]: item["values"][0] for item in lead["field_data"]}
|
||||||
crm_lead_data = {question_to_field_map.get(k): v for
|
crm_lead_data = {
|
||||||
k, v in lead_data.items() if k in question_to_field_map
|
question_to_field_map.get(k): v for k, v in lead_data.items() if k in question_to_field_map
|
||||||
}
|
}
|
||||||
crm_lead_data["source"] = "Facebook"
|
crm_lead_data["source"] = "Facebook"
|
||||||
|
crm_lead_data["facebook_lead_id"] = lead["id"]
|
||||||
|
|
||||||
|
try:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "CRM Lead",
|
"doctype": "CRM Lead",
|
||||||
**crm_lead_data,
|
**crm_lead_data,
|
||||||
}
|
}
|
||||||
).insert(ignore_permissions=True)
|
).insert(ignore_permissions=True)
|
||||||
|
except frappe.UniqueValidationError:
|
||||||
|
# Skip duplicate leads based on facebook_lead_id
|
||||||
|
frappe.log_error("Duplicate lead skipped")
|
||||||
|
continue
|
||||||
|
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Lead Sync Source", {"facebook_lead_form": lead_form_id}, "last_synced_at", frappe.utils.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_and_store_pages_from_facebook(access_token: str) -> None:
|
def fetch_and_store_pages_from_facebook(access_token: str) -> None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user