update
This commit is contained in:
parent
92a3a1bed7
commit
c291a02a89
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from urllib.parse import quote
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
|
@ -164,3 +165,32 @@ class SeeyonClient(BaseClient):
|
|||
json=body,
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
|
||||
def get_org_members_by_code(self, *, code: str, pageNo: int = 0, pageSize: int = 20) -> list[dict[str, Any]]:
|
||||
"""
|
||||
按人员编码查询 OA 人员信息:
|
||||
GET /seeyon/rest/orgMembers/code/{code}?pageNo={pageNo}&pageSize={pageSize}
|
||||
"""
|
||||
c = str(code or "").strip()
|
||||
if not c:
|
||||
raise ValueError("code is required")
|
||||
if pageNo < 0:
|
||||
pageNo = 0
|
||||
if pageSize <= 0:
|
||||
pageSize = 20
|
||||
path = f"/seeyon/rest/orgMembers/code/{quote(c, safe='')}"
|
||||
resp = self.request("GET", path, params={"pageNo": pageNo, "pageSize": pageSize})
|
||||
payload = resp.json() if resp.content else {}
|
||||
if isinstance(payload, list):
|
||||
return [x for x in payload if isinstance(x, dict)]
|
||||
if isinstance(payload, dict):
|
||||
data = payload.get("data")
|
||||
if isinstance(data, list):
|
||||
return [x for x in data if isinstance(x, dict)]
|
||||
if isinstance(data, dict):
|
||||
items = data.get("content")
|
||||
if isinstance(items, list):
|
||||
return [x for x in items if isinstance(x, dict)]
|
||||
return [data]
|
||||
return [payload]
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@ def _cell_value(cell: Any) -> str:
|
|||
return str(cell or "").strip()
|
||||
|
||||
|
||||
def _cell_show_value(cell: Any) -> str:
|
||||
if isinstance(cell, dict):
|
||||
return str(cell.get("showValue") or "").strip()
|
||||
return ""
|
||||
|
||||
|
||||
def _date_only(s: Any) -> str:
|
||||
v = str(s or "").strip()
|
||||
if not v:
|
||||
|
|
@ -148,6 +154,20 @@ def _extract_staff_code(staff_profile: dict[str, Any]) -> str:
|
|||
).strip()
|
||||
|
||||
|
||||
def _pick_best_member_by_code(members: list[dict[str, Any]]) -> dict[str, Any] | None:
|
||||
if not members:
|
||||
return None
|
||||
# 优先:可用且在职
|
||||
for m in members:
|
||||
if bool(m.get("isValid", True)) and int(m.get("state", 1) or 1) == 1:
|
||||
return m
|
||||
# 次优:enabled
|
||||
for m in members:
|
||||
if bool(m.get("enabled", True)):
|
||||
return m
|
||||
return members[0]
|
||||
|
||||
|
||||
def _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict[str, Any]]:
|
||||
"""
|
||||
兼容不同 OA export 返回结构,提取:
|
||||
|
|
@ -391,12 +411,28 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
code = _extract_staff_code(profile)
|
||||
if code:
|
||||
user_id_to_staff_code[int(uid)] = code
|
||||
# 3.4) 将 HRBP/汇报人工号转换为 OA 人员ID(member 字段要求)
|
||||
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]] = {}
|
||||
for code in need_member_codes:
|
||||
try:
|
||||
members = seeyon.get_org_members_by_code(code=code, pageNo=0, pageSize=20)
|
||||
best = _pick_best_member_by_code(members)
|
||||
if not best:
|
||||
continue
|
||||
member_id = str(best.get("id") or "").strip()
|
||||
member_name = str(best.get("name") or best.get("loginName") or "").strip()
|
||||
if member_id:
|
||||
code_to_member[code] = {"id": member_id, "name": member_name}
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.warning("OA 人员查询失败:code=%s err=%r", code, e)
|
||||
logger.info(
|
||||
"人员工号反查完成:staff_profiles=%s reportings=%s hrbp_ids=%s resolved_staff_codes=%s",
|
||||
"人员工号反查完成:staff_profiles=%s reportings=%s hrbp_ids=%s resolved_staff_codes=%s resolved_member_ids=%s",
|
||||
len(staff_profile_by_user_id),
|
||||
len(reporting_user_ids),
|
||||
len(hrbp_user_ids),
|
||||
len(user_id_to_staff_code),
|
||||
len(code_to_member),
|
||||
)
|
||||
if verbose_trace:
|
||||
for job_no in list(ehr_by_job_no.keys()):
|
||||
|
|
@ -427,13 +463,19 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
leave_date = _date_only(rec.get("lastWorkDate"))
|
||||
id_number = str(emp.get("iDNumber") or "")
|
||||
hrbp_uid = _to_int_safe(rec.get(_EHR_HRBP_ID_KEY) or _custom_prop_value(rec.get("customProperties"), _EHR_HRBP_ID_KEY))
|
||||
hrbp = str(user_id_to_staff_code.get(hrbp_uid) or "")
|
||||
hrbp_code = str(user_id_to_staff_code.get(hrbp_uid) or "")
|
||||
hrbp_member = code_to_member.get(hrbp_code, {})
|
||||
hrbp = str(hrbp_member.get("id") or "")
|
||||
hrbp_show = str(hrbp_member.get("name") or hrbp_code)
|
||||
manager_uid = _extract_reporting_user_id(staff_profile_by_user_id.get(user_id, {}))
|
||||
manager = str(user_id_to_staff_code.get(manager_uid) or "")
|
||||
manager_code = str(user_id_to_staff_code.get(manager_uid) or "")
|
||||
manager_member = code_to_member.get(manager_code, {})
|
||||
manager = str(manager_member.get("id") or "")
|
||||
manager_show = str(manager_member.get("name") or manager_code)
|
||||
is_leaving = "是" if _date_only(rec.get("lastWorkDate")) else "否"
|
||||
domain_account = _custom_prop_value(emp.get("customProperties"), domain_custom_key) or str(emp.get("_Name") or "")
|
||||
logger.info(
|
||||
"EHR 字段预览:job_no=%s company=%s name=%s rd_attr=%s place=%s entry_date=%s leave_date=%s id_number=%s hrbp=%s manager=%s is_leaving=%s domain_account=%s",
|
||||
"EHR 字段预览:job_no=%s company=%s name=%s rd_attr=%s place=%s entry_date=%s leave_date=%s id_number=%s hrbp_id=%s hrbp_show=%s manager_id=%s manager_show=%s is_leaving=%s domain_account=%s",
|
||||
job_no,
|
||||
company,
|
||||
name,
|
||||
|
|
@ -443,7 +485,9 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
leave_date,
|
||||
id_number,
|
||||
hrbp,
|
||||
hrbp_show,
|
||||
manager,
|
||||
manager_show,
|
||||
is_leaving,
|
||||
domain_account,
|
||||
)
|
||||
|
|
@ -652,9 +696,15 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
leave_date = _date_only(rec.get("lastWorkDate"))
|
||||
id_number = str(emp.get("iDNumber") or "")
|
||||
hrbp_uid = _to_int_safe(rec.get(_EHR_HRBP_ID_KEY) or _custom_prop_value(rec.get("customProperties"), _EHR_HRBP_ID_KEY))
|
||||
hrbp = str(user_id_to_staff_code.get(hrbp_uid) or "")
|
||||
hrbp_code = str(user_id_to_staff_code.get(hrbp_uid) or "")
|
||||
hrbp_member = code_to_member.get(hrbp_code, {})
|
||||
hrbp = str(hrbp_member.get("id") or "")
|
||||
hrbp_show = str(hrbp_member.get("name") or hrbp_code)
|
||||
manager_uid = _extract_reporting_user_id(staff_profile_by_user_id.get(user_id, {}))
|
||||
manager = str(user_id_to_staff_code.get(manager_uid) or "")
|
||||
manager_code = str(user_id_to_staff_code.get(manager_uid) or "")
|
||||
manager_member = code_to_member.get(manager_code, {})
|
||||
manager = str(manager_member.get("id") or "")
|
||||
manager_show = str(manager_member.get("name") or manager_code)
|
||||
is_leaving = "是" if _date_only(rec.get("lastWorkDate")) else "否"
|
||||
domain_account = _custom_prop_value(emp.get("customProperties"), domain_custom_key) or str(emp.get("_Name") or "")
|
||||
|
||||
|
|
@ -668,6 +718,8 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
id_number = _prefer_non_empty(id_number, _cell_value(existing_field_map.get(display_to_code["身份证号"])))
|
||||
hrbp = _prefer_non_empty(hrbp, _cell_value(existing_field_map.get(display_to_code["HRBP"])))
|
||||
manager = _prefer_non_empty(manager, _cell_value(existing_field_map.get(display_to_code["汇报人"])))
|
||||
hrbp_show = _prefer_non_empty(hrbp_show, _cell_show_value(existing_field_map.get(display_to_code["HRBP"])))
|
||||
manager_show = _prefer_non_empty(manager_show, _cell_show_value(existing_field_map.get(display_to_code["汇报人"])))
|
||||
is_leaving = _prefer_non_empty(is_leaving, _cell_value(existing_field_map.get(display_to_code["在离职"])))
|
||||
domain_account = _prefer_non_empty(domain_account, _cell_value(existing_field_map.get(display_to_code["域账号"])))
|
||||
|
||||
|
|
@ -679,8 +731,8 @@ class SyncEhrToOaFormJob(BaseJob):
|
|||
{"name": display_to_code["入职日期"], "value": entry_date, "showValue": entry_date},
|
||||
{"name": display_to_code["离职日期"], "value": leave_date, "showValue": leave_date},
|
||||
{"name": display_to_code["身份证号"], "value": id_number, "showValue": id_number},
|
||||
{"name": display_to_code["HRBP"], "value": hrbp, "showValue": hrbp},
|
||||
{"name": display_to_code["汇报人"], "value": manager, "showValue": manager},
|
||||
{"name": display_to_code["HRBP"], "value": hrbp, "showValue": hrbp_show},
|
||||
{"name": display_to_code["汇报人"], "value": manager, "showValue": manager_show},
|
||||
{"name": display_to_code["在离职"], "value": is_leaving, "showValue": is_leaving},
|
||||
{"name": display_to_code["域账号"], "value": domain_account, "showValue": domain_account},
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue