Files
upstream-frappe-crm/crm/patches/v1_0/add_enrichment_fields_to_layouts.py
upstream-mirror db69de1c11
Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 1s
snapshot of https://github.com/frappe/crm.git (develop, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:36:01 +05:00

79 lines
2.4 KiB
Python

"""Expose the Domain Enrichment fields on existing sites.
The enrichment fields (company_description, linkedin, twitter, facebook) were added
to the default Lead/Deal/Organization layouts in ``crm/install.py``, but that seeder
is skip-if-exists -- so sites installed before this feature never get them and users
can't see what enrichment writes. This patch injects any missing enrichment field
into the relevant Side Panel / Data Fields / Quick Entry layouts. Idempotent: a
field already present anywhere in the layout (or absent from the doctype) is left
untouched.
"""
import json
import frappe
ENRICHMENT_FIELDS = ["company_description", "linkedin", "twitter", "facebook"]
TARGET_LAYOUTS = [
"CRM Lead-Side Panel",
"CRM Deal-Side Panel",
"CRM Organization-Side Panel",
"CRM Lead-Data Fields",
"CRM Deal-Data Fields",
# Quick Entry = the create-modal layout; enrichment fields must be visible there.
"CRM Lead-Quick Entry",
"CRM Deal-Quick Entry",
"CRM Organization-Quick Entry",
]
def _iter_columns(layout):
"""Yield every column dict in a layout tree (handles tabbed layouts that nest
sections under a top-level section's ``sections`` key)."""
for section in layout:
yield from section.get("columns", [])
for nested in section.get("sections", []):
yield from nested.get("columns", [])
def _visible_columns(layout):
"""Columns of the first non-hidden section (handles tabbed layouts). Skipping
hidden sections matters for Quick Entry, whose first section (organization) is
hidden -- fields must land in a section the user can actually see."""
for section in layout:
if section.get("hidden"):
continue
if section.get("columns"):
return section["columns"]
for nested in section.get("sections", []):
if not nested.get("hidden") and nested.get("columns"):
return nested["columns"]
return None
def execute():
for name in TARGET_LAYOUTS:
if not frappe.db.exists("CRM Fields Layout", name):
continue
doc = frappe.get_doc("CRM Fields Layout", name)
try:
layout = json.loads(doc.layout or "[]")
except (ValueError, TypeError):
continue
present = {f for col in _iter_columns(layout) for f in col.get("fields", [])}
meta = frappe.get_meta(doc.dt)
missing = [f for f in ENRICHMENT_FIELDS if f not in present and meta.has_field(f)]
if not missing:
continue
target = _visible_columns(layout)
if not target:
continue
target[0].setdefault("fields", []).extend(missing)
doc.layout = json.dumps(layout)
doc.save()