feat: map fields for syncing
This commit is contained in:
parent
d0cccc2e61
commit
3ac4a582f5
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on("Facebook Lead Form", {
|
||||||
|
refresh(frm) {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "field:id",
|
||||||
|
"creation": "2025-09-26 19:01:48.325681",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"page",
|
||||||
|
"id",
|
||||||
|
"column_break_ahyo",
|
||||||
|
"form_name",
|
||||||
|
"section_break_iqhq",
|
||||||
|
"questions"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "page",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Page",
|
||||||
|
"options": "Facebook Page",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "ID",
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_ahyo",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "form_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Form Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_iqhq",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "questions",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Questions",
|
||||||
|
"options": "Facebook Lead Form Question"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grid_page_length": 50,
|
||||||
|
"in_create": 1,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2025-09-29 18:50:19.215513",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Lead Syncing",
|
||||||
|
"name": "Facebook Lead Form",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"owner": "hussain@frappe.io",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
|
"show_title_field_in_link": 1,
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "form_name"
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class FacebookLeadForm(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.lead_syncing.doctype.facebook_lead_form_question.facebook_lead_form_question import FacebookLeadFormQuestion
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
form_name: DF.Data | None
|
||||||
|
id: DF.Data | None
|
||||||
|
page: DF.Link
|
||||||
|
questions: DF.Table[FacebookLeadFormQuestion]
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
|
pass
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests import IntegrationTestCase
|
||||||
|
|
||||||
|
|
||||||
|
# On IntegrationTestCase, the doctype test records and all
|
||||||
|
# link-field test record dependencies are recursively loaded
|
||||||
|
# Use these module variables to add/remove to/from that list
|
||||||
|
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class IntegrationTestFacebookLeadForm(IntegrationTestCase):
|
||||||
|
"""
|
||||||
|
Integration tests for FacebookLeadForm.
|
||||||
|
Use this class for testing interactions between multiple components.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
@ -10,7 +10,8 @@
|
|||||||
"id",
|
"id",
|
||||||
"column_break_hgde",
|
"column_break_hgde",
|
||||||
"key",
|
"key",
|
||||||
"type"
|
"type",
|
||||||
|
"mapped_to_crm_field"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -40,13 +41,20 @@
|
|||||||
"fieldname": "id",
|
"fieldname": "id",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "ID"
|
"label": "ID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Not Synced",
|
||||||
|
"fieldname": "mapped_to_crm_field",
|
||||||
|
"fieldtype": "Autocomplete",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Mapped to CRM Field"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-09-26 19:48:30.897092",
|
"modified": "2025-09-29 18:45:21.800960",
|
||||||
"modified_by": "hussain@frappe.io",
|
"modified_by": "hussain@frappe.io",
|
||||||
"module": "Lead Syncing",
|
"module": "Lead Syncing",
|
||||||
"name": "Facebook Lead Form Question",
|
"name": "Facebook Lead Form Question",
|
||||||
|
|||||||
@ -17,6 +17,7 @@ class FacebookLeadFormQuestion(Document):
|
|||||||
id: DF.Data | None
|
id: DF.Data | None
|
||||||
key: DF.Data
|
key: DF.Data
|
||||||
label: DF.Data | None
|
label: DF.Data | None
|
||||||
|
mapped_to_crm_field: DF.Autocomplete | None
|
||||||
parent: DF.Data
|
parent: DF.Data
|
||||||
parentfield: DF.Data
|
parentfield: DF.Data
|
||||||
parenttype: DF.Data
|
parenttype: DF.Data
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"allow_rename": 1,
|
|
||||||
"creation": "2025-09-26 18:54:57.313880",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"source_field_name",
|
|
||||||
"column_break_zbml",
|
|
||||||
"crm_field_name"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "source_field_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Source Field Name",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_zbml",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "crm_field_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "CRM Field Name",
|
|
||||||
"reqd": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"grid_page_length": 50,
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"istable": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2025-09-26 18:55:59.773584",
|
|
||||||
"modified_by": "hussain@frappe.io",
|
|
||||||
"module": "Lead Syncing",
|
|
||||||
"name": "Lead Form Field Mapping",
|
|
||||||
"owner": "hussain@frappe.io",
|
|
||||||
"permissions": [],
|
|
||||||
"row_format": "Dynamic",
|
|
||||||
"sort_field": "creation",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"states": []
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class LeadFormFieldMapping(Document):
|
|
||||||
pass
|
|
||||||
@ -10,8 +10,6 @@
|
|||||||
"access_token",
|
"access_token",
|
||||||
"column_break_lwcw",
|
"column_break_lwcw",
|
||||||
"last_synced_at",
|
"last_synced_at",
|
||||||
"section_break_itlk",
|
|
||||||
"field_mapping",
|
|
||||||
"facebook_tab",
|
"facebook_tab",
|
||||||
"facebook_page",
|
"facebook_page",
|
||||||
"column_break_uxlr",
|
"column_break_uxlr",
|
||||||
@ -40,16 +38,6 @@
|
|||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"label": "Access Token"
|
"label": "Access Token"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "section_break_itlk",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "field_mapping",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "Field Mapping",
|
|
||||||
"options": "Lead Form Field Mapping"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.type===\"Facebook\"",
|
"depends_on": "eval:doc.type===\"Facebook\"",
|
||||||
"fieldname": "facebook_tab",
|
"fieldname": "facebook_tab",
|
||||||
@ -76,7 +64,7 @@
|
|||||||
"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-26 19:04:31.584094",
|
"modified": "2025-09-29 18:45:32.305860",
|
||||||
"modified_by": "hussain@frappe.io",
|
"modified_by": "hussain@frappe.io",
|
||||||
"module": "Lead Syncing",
|
"module": "Lead Syncing",
|
||||||
"name": "Lead Sync Source",
|
"name": "Lead Sync Source",
|
||||||
|
|||||||
@ -17,6 +17,22 @@ def get_fb_graph_api_url(endpoint: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
class LeadSyncSource(Document):
|
class LeadSyncSource(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 frappe.types import DF
|
||||||
|
|
||||||
|
access_token: DF.SmallText | None
|
||||||
|
facebook_lead_form: DF.Link | None
|
||||||
|
facebook_page: DF.Link | None
|
||||||
|
last_synced_at: DF.Datetime | None
|
||||||
|
name: DF.Int | None
|
||||||
|
type: DF.Literal["Facebook"]
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
if self.type == "Facebook" and self.access_token:
|
if self.type == "Facebook" and self.access_token:
|
||||||
fetch_and_store_pages_from_facebook(self.access_token)
|
fetch_and_store_pages_from_facebook(self.access_token)
|
||||||
@ -38,12 +54,28 @@ def sync_leads_from_facebook(access_token: str, lead_form_id: str) -> None:
|
|||||||
"limit": 15000,
|
"limit": 15000,
|
||||||
},
|
},
|
||||||
).get("data", [])
|
).get("data", [])
|
||||||
|
|
||||||
|
form_questions = frappe.db.get_all(
|
||||||
|
"Facebook Lead Form Question", filters={"parent": lead_form_id}, fields=["key", "mapped_to_crm_field"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Map form questions to CRM Lead fields
|
||||||
|
question_to_field_map = {q["key"]: q["mapped_to_crm_field"]
|
||||||
|
for q in form_questions
|
||||||
|
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"]}
|
||||||
|
crm_lead_data = {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"
|
||||||
|
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "CRM Lead",
|
"doctype": "CRM Lead",
|
||||||
"first_name": lead["field_data"][0]["values"][0],
|
**crm_lead_data,
|
||||||
"source": "Facebook",
|
|
||||||
}
|
}
|
||||||
).insert(ignore_permissions=True)
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user