Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions crm/lead_syncing/doctype/lead_sync_source/facebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def fetch_and_store_pages_from_facebook(access_token: str) -> list[dict]:
for page in pages:
page_id = page["id"]
already_synced = frappe.db.exists("Facebook Page", page_id)
page["is_new"] = not already_synced
if not already_synced:
create_facebook_page_in_db(page, account_details)
forms = fetch_and_store_leadgen_forms_from_facebook(page_id, page["access_token"])
Expand Down Expand Up @@ -195,6 +196,7 @@ def fetch_and_store_leadgen_forms_from_facebook(page_id: str, page_access_token:
for form in forms:
form_id = form["id"]
already_synced = frappe.db.exists("Facebook Lead Form", form_id)
form["is_new"] = not already_synced
if already_synced:
continue
create_facebook_lead_form_in_db(form, page_id)
Expand Down Expand Up @@ -222,3 +224,35 @@ def get_pages_with_forms() -> list[dict]:
forms = frappe.db.get_all("Facebook Lead Form", filters={"page": page["id"]}, fields=["id", "name"])
page["forms"] = forms
return pages


@frappe.whitelist()
def refresh_facebook_forms(source_name: str) -> dict:
"""Refresh Facebook pages and forms for an existing sync source.

This fetches any new pages and forms that were created on Facebook
after the sync source was initially set up.
"""
source = frappe.get_doc("Lead Sync Source", source_name)
if source.type != "Facebook":
frappe.throw(frappe._("This sync source is not a Facebook source"))

access_token = source.get_password("access_token")
if not access_token:
frappe.throw(frappe._("Access token is required"))

pages = fetch_and_store_pages_from_facebook(access_token)

new_forms_count = 0
new_pages_count = 0
for page in pages:
if page.get("is_new"):
new_pages_count += 1
for form in page.get("forms", []):
if form.get("is_new"):
new_forms_count += 1

return {
"new_pages_count": new_pages_count,
"new_forms_count": new_forms_count,
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,16 @@
<FormControl v-if="!isLocal && sourceDoc && sourceDoc.last_synced_at"
:modelValue="formatDate(sourceDoc.last_synced_at)" disabled type="datetime" :label="__('Last Synced At')" />

<Link v-if="!isLocal" label="Facebook Page" v-model="syncSource.facebook_page"
doctype="Facebook Page" />
<div v-if="!isLocal" class="flex items-end gap-2">
<Link class="flex-1" label="Facebook Page" v-model="syncSource.facebook_page"
doctype="Facebook Page" />
<Button variant="outline" :loading="refreshFormsResource.loading"
@click="refreshForms" :title="__('Refresh pages and forms from Facebook')">
<template #icon>
<LucideRefreshCw class="size-4" />
</template>
</Button>
</div>

<Link v-if="!isLocal && syncSource.facebook_page" label="Lead Form"
v-model="syncSource.facebook_lead_form" doctype="Facebook Lead Form" :filters="{
Expand Down Expand Up @@ -112,6 +120,7 @@ import { getMeta } from "@/stores/meta";
import Link from "@/components/Controls/Link.vue";
import Grid from "@/components/Controls/Grid.vue";
import LucideCircleQuestionMark from '~icons/lucide/circle-question-mark';
import LucideRefreshCw from '~icons/lucide/refresh-cw';
import FailureLogs from "./FailureLogs.vue";
import DetailsIcon from '@/components/Icons/DetailsIcon.vue'
import RefreshIcon from '@/components/Icons/RefreshIcon.vue'
Expand Down Expand Up @@ -319,6 +328,26 @@ const leadFields = createResource({
},
});

const refreshFormsResource = createResource({
url: "crm.lead_syncing.doctype.lead_sync_source.facebook.refresh_facebook_forms",
onSuccess: (data) => {
if (data.new_forms_count > 0 || data.new_pages_count > 0) {
toast.success(__("{0} new page(s) and {1} new form(s) synced", [data.new_pages_count, data.new_forms_count]));
} else {
toast.info(__("No new pages or forms found"));
}
},
onError: (e) => {
toast.error(e.messages?.[0] || __("Error refreshing forms"));
},
});

function refreshForms() {
refreshFormsResource.submit({
source_name: syncSource.value.name,
});
}

const getCRMLeadFields = computed(() => {
if (leadFields.data) {
return leadFields.data.map((field) => ({
Expand Down