This commit is contained in:
Marsway 2026-04-30 17:09:41 +08:00
parent 51a488a5cb
commit 2992a2631c
1 changed files with 85 additions and 17 deletions

View File

@ -38,12 +38,17 @@ def _to_int_safe(v: Any) -> int:
def _scalar_value(raw: Any) -> str:
if isinstance(raw, dict):
val = raw.get("value")
if val is None or str(val).strip() == "":
val = raw.get("showValue")
val = None
for value_key in ("value", "showValue", "text", "Text", "displayValue", "DisplayValue"):
val = raw.get(value_key)
if val is not None and str(val).strip() != "":
break
if isinstance(val, (dict, list, tuple, set)):
return _scalar_value(val)
return str(val or "").strip()
if isinstance(raw, (list, tuple, set)):
return "\n".join([str(x).strip() for x in raw if x is not None and str(x).strip() != ""])
values = [_scalar_value(x) for x in raw]
return "\n".join([x for x in values if x])
return str(raw or "").strip()
@ -70,6 +75,76 @@ def _translate_value(node: dict[str, Any], key: str | None) -> str:
return ""
def _candidate_keys(key: str | None) -> list[str]:
if not key:
return []
candidates = [key, f"{key}Text"]
if key.endswith("Text"):
candidates.insert(0, key)
candidates.append(key[:-4])
out: list[str] = []
seen: set[str] = set()
for candidate in candidates:
s = str(candidate or "").strip()
if s and s not in seen:
seen.add(s)
out.append(s)
return out
def _deep_field_value(node: Any, key: str | None) -> str:
candidates = set(_candidate_keys(key))
if not candidates:
return ""
if isinstance(node, dict):
for candidate in candidates:
if candidate in node:
s = _scalar_value(node.get(candidate))
if s:
return s
for value in node.values():
s = _deep_field_value(value, key)
if s:
return s
elif isinstance(node, list):
for value in node:
s = _deep_field_value(value, key)
if s:
return s
return ""
def _collect_matching_keys(node: Any, keyword: str, *, limit: int = 30) -> list[str]:
matches: list[str] = []
seen: set[str] = set()
needle = str(keyword or "").lower()
if not needle:
return matches
def walk(current: Any) -> None:
if len(matches) >= limit:
return
if isinstance(current, dict):
for k, v in current.items():
key = str(k)
if needle in key.lower() and key not in seen:
seen.add(key)
matches.append(key)
if len(matches) >= limit:
return
walk(v)
if len(matches) >= limit:
return
elif isinstance(current, list):
for v in current:
walk(v)
if len(matches) >= limit:
return
walk(node)
return matches
def _field_value(item: dict[str, Any], key: str) -> str:
emp = item.get("employeeInfo") or {}
rec = item.get("recordInfo") or {}
@ -85,18 +160,9 @@ def _field_value(item: dict[str, Any], key: str) -> str:
s = _custom_prop_value(node.get("customProperties"), key)
if s:
return s
for child in node.values():
if not isinstance(child, dict):
continue
s = _scalar_value(child.get(key))
if s:
return s
s = _translate_value(child, key)
if s:
return s
s = _custom_prop_value(child.get("customProperties"), key)
if s:
return s
s = _deep_field_value(node, key)
if s:
return s
return ""
@ -555,11 +621,13 @@ class SyncEhrToAdUserJob(BaseJob):
workplace_text = _field_translate_or_value(item, work_location_text_key)
street_address = _field_value(item, street_address_key)
if verbose_trace:
address_candidate_keys = _collect_matching_keys(item, "extgzddxx") if not street_address else []
logger.info(
"AD 地址字段解析sam=%s street_address_key=%s streetAddress=%r",
"AD 地址字段解析sam=%s street_address_key=%s streetAddress=%r candidate_keys=%s",
sam,
street_address_key,
street_address,
address_candidate_keys,
)
company = default_company or _root_org_name(org, org_by_oid)
location_attrs = _location_from_workplace(workplace_text or office, location_mappings)