This commit is contained in:
Marsway 2026-03-26 13:56:30 +08:00
parent 76a17f5274
commit b502b11bba
2 changed files with 67 additions and 24 deletions

View File

@ -491,28 +491,55 @@ class SyncEhrToOaApi:
for i in range(0, len(clean_ids), chunk_size):
chunk = clean_ids[i : i + chunk_size]
for uid in chunk:
resp = self._client.request(
"GET",
"/UserFrameworkApiV3/api/v1/staffs/Get",
params={"userId": uid},
)
payload = resp.json() if resp.content else {}
# 兼容多种返回结构
data = payload.get("data", payload)
if isinstance(data, list):
items = [x for x in data if isinstance(x, dict)]
if items:
out[uid] = items[0]
continue
if isinstance(data, dict):
# 可能是单条,也可能是 map
if "userId" in data or "UserId" in data:
out[uid] = data
else:
# map 场景key=uid
d2 = data.get(str(uid))
if isinstance(d2, dict):
out[uid] = d2
# 非 200 业务码场景不硬失败,避免单个用户影响全量
profile: dict[str, Any] | None = None
for params in ({"userId": str(uid)}, {"userid": str(uid)}):
try:
resp = self._client.request(
"GET",
"/UserFrameworkApiV3/api/v1/staffs/Get",
params=params,
)
except Exception:
continue
payload = resp.json() if resp.content else {}
profile = self._find_staff_profile_by_uid(payload, uid)
if profile is not None:
break
if profile is not None:
out[uid] = profile
logger.info("EHR 员工详情查询完成input_user_ids=%s matched_profiles=%s", len(clean_ids), len(out))
return out
@staticmethod
def _find_staff_profile_by_uid(payload: Any, uid: int) -> dict[str, Any] | None:
def _iter_dicts(node: Any):
if isinstance(node, dict):
yield node
for v in node.values():
yield from _iter_dicts(v)
elif isinstance(node, list):
for it in node:
yield from _iter_dicts(it)
def _uid_from_dict(d: dict[str, Any]) -> int:
for k in ("userId", "UserId", "userid", "UserID", "id", "Id", "ID"):
if k in d:
try:
return int(str(d.get(k)).strip())
except Exception:
continue
return 0
best: dict[str, Any] | None = None
for d in _iter_dicts(payload):
if not isinstance(d, dict):
continue
duid = _uid_from_dict(d)
if duid != uid:
continue
# 优先返回带工号字段的对象
if any(k in d for k in ("staffCode", "StaffCode", "code", "Code", "jobNumber", "JobNumber", "employeeNo", "EmployeeNo")):
return d
if best is None:
best = d
return best

View File

@ -355,10 +355,12 @@ class SyncEhrToOaFormJob(BaseJob):
# 3) 员工按工号归并(同工号保留“最新”记录)
ehr_by_job_no: dict[str, dict[str, Any]] = {}
ehr_by_job_no_norm: dict[str, dict[str, Any]] = {}
ehr_user_id_to_job_no: dict[int, str] = {}
for item in emp_rows:
if not isinstance(item, dict):
continue
record = item.get("recordInfo") or {}
emp_info = item.get("employeeInfo") or {}
if not isinstance(record, dict):
continue
job_no = str(record.get("jobNumber") or "").strip()
@ -370,12 +372,19 @@ class SyncEhrToOaFormJob(BaseJob):
if job_no_norm:
ex2 = ehr_by_job_no_norm.get(job_no_norm)
ehr_by_job_no_norm[job_no_norm] = item if ex2 is None else _choose_better_record(ex2, item)
try:
uid = int((emp_info or {}).get("userID"))
except Exception:
uid = 0
if uid > 0 and uid not in ehr_user_id_to_job_no:
ehr_user_id_to_job_no[uid] = job_no
logger.info(
"EHR 数据准备完成employee_rows=%s organization_rows=%s distinct_job_numbers=%s distinct_job_numbers_norm=%s",
"EHR 数据准备完成employee_rows=%s organization_rows=%s distinct_job_numbers=%s distinct_job_numbers_norm=%s userid_jobno_map=%s",
len(emp_rows),
len(org_rows),
len(ehr_by_job_no),
len(ehr_by_job_no_norm),
len(ehr_user_id_to_job_no),
)
# 3.1) 按员工 UserID 查询合同主体公司firstParty作为“所属公司”的优先来源
contract_user_ids: list[int] = []
@ -424,6 +433,10 @@ class SyncEhrToOaFormJob(BaseJob):
code = _extract_staff_code(profile)
if code:
user_id_to_staff_code[int(uid)] = code
# 兜底:若 staffs/Get 未返回工号,尝试从本次员工数据中反查
for uid in resolve_user_ids:
if int(uid) not in user_id_to_staff_code and int(uid) in ehr_user_id_to_job_no:
user_id_to_staff_code[int(uid)] = ehr_user_id_to_job_no[int(uid)]
# 3.4) 将 HRBP/汇报人工号转换为 OA 人员IDmember 字段要求)
need_member_codes = list({c for c in user_id_to_staff_code.values() if str(c or "").strip()})
code_to_member: dict[str, dict[str, str]] = {}
@ -448,6 +461,9 @@ class SyncEhrToOaFormJob(BaseJob):
len(user_id_to_staff_code),
len(code_to_member),
)
if verbose_trace:
sample_codes = list(user_id_to_staff_code.items())[:30]
logger.info("人员工号反查样本(uid->code)=%s", sample_codes)
if verbose_trace:
for job_no in list(ehr_by_job_no.keys()):
logger.info("EHR 工号明细raw=%s norm=%s", job_no, _normalize_job_no(job_no))