fixing
This commit is contained in:
parent
7d6ac687da
commit
0928492ae4
|
|
@ -79,23 +79,6 @@ def _normalize_job_no(v: Any) -> str:
|
||||||
return s.upper()
|
return s.upper()
|
||||||
|
|
||||||
|
|
||||||
def _to_int_candidate(v: Any) -> int | None:
|
|
||||||
if v is None:
|
|
||||||
return None
|
|
||||||
if isinstance(v, dict):
|
|
||||||
v = _cell_value(v)
|
|
||||||
s = str(v).strip()
|
|
||||||
if not s:
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
# 兼容 "123.0"
|
|
||||||
if "." in s and s.endswith(".0"):
|
|
||||||
return int(float(s))
|
|
||||||
return int(s)
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict[str, Any]]:
|
def _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
兼容不同 OA export 返回结构,提取:
|
兼容不同 OA export 返回结构,提取:
|
||||||
|
|
@ -111,20 +94,14 @@ def _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict
|
||||||
for k, v in master.items():
|
for k, v in master.items():
|
||||||
if isinstance(k, str) and k.startswith("field"):
|
if isinstance(k, str) and k.startswith("field"):
|
||||||
field_map[k] = v
|
field_map[k] = v
|
||||||
# 常见主键位置优先尝试
|
for candidate in (row.get("id"), row.get("masterDataId"), master.get("id")):
|
||||||
for candidate in (
|
if candidate is None:
|
||||||
row.get("id"),
|
continue
|
||||||
row.get("masterDataId"),
|
try:
|
||||||
master.get("id"),
|
row_id = int(str(candidate))
|
||||||
master.get("ID"),
|
|
||||||
master.get("recordId"),
|
|
||||||
master.get("dataId"),
|
|
||||||
master.get("_id"),
|
|
||||||
):
|
|
||||||
rid = _to_int_candidate(candidate)
|
|
||||||
if rid is not None:
|
|
||||||
row_id = rid
|
|
||||||
break
|
break
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
# 结构 B:masterTable.record.fields = [{name,value,showValue}, ...]
|
# 结构 B:masterTable.record.fields = [{name,value,showValue}, ...]
|
||||||
master_table = row.get("masterTable")
|
master_table = row.get("masterTable")
|
||||||
|
|
@ -140,7 +117,12 @@ def _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict
|
||||||
if name:
|
if name:
|
||||||
field_map[name] = fld
|
field_map[name] = fld
|
||||||
if row_id is None:
|
if row_id is None:
|
||||||
row_id = _to_int_candidate(record.get("id"))
|
rid = record.get("id")
|
||||||
|
if rid is not None:
|
||||||
|
try:
|
||||||
|
row_id = int(str(rid))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 结构 C:行级 fields 列表
|
# 结构 C:行级 fields 列表
|
||||||
row_fields = row.get("fields")
|
row_fields = row.get("fields")
|
||||||
|
|
@ -226,6 +208,12 @@ class SyncEhrToOaFormJob(BaseJob):
|
||||||
verbose_trace = _to_bool_or_none(params.get("verbose_trace"))
|
verbose_trace = _to_bool_or_none(params.get("verbose_trace"))
|
||||||
if verbose_trace is None:
|
if verbose_trace is None:
|
||||||
verbose_trace = True
|
verbose_trace = True
|
||||||
|
preview_ehr_data = _to_bool_or_none(params.get("preview_ehr_data"))
|
||||||
|
if preview_ehr_data is None:
|
||||||
|
preview_ehr_data = True
|
||||||
|
preview_limit = int(params.get("preview_limit") or 20)
|
||||||
|
if preview_limit <= 0:
|
||||||
|
preview_limit = 20
|
||||||
|
|
||||||
seeyon = SeeyonClient(base_url=oa_base_url, rest_user=rest_user, rest_password=rest_password, loginName=login_name)
|
seeyon = SeeyonClient(base_url=oa_base_url, rest_user=rest_user, rest_password=rest_password, loginName=login_name)
|
||||||
ehr = SyncEhrToOaApi(secret_params={"app_key": app_key, "app_secret": app_secret})
|
ehr = SyncEhrToOaApi(secret_params={"app_key": app_key, "app_secret": app_secret})
|
||||||
|
|
@ -277,6 +265,51 @@ class SyncEhrToOaFormJob(BaseJob):
|
||||||
if verbose_trace:
|
if verbose_trace:
|
||||||
for job_no in list(ehr_by_job_no.keys()):
|
for job_no in list(ehr_by_job_no.keys()):
|
||||||
logger.info("EHR 工号明细:raw=%s norm=%s", job_no, _normalize_job_no(job_no))
|
logger.info("EHR 工号明细:raw=%s norm=%s", job_no, _normalize_job_no(job_no))
|
||||||
|
if preview_ehr_data:
|
||||||
|
logger.info("EHR 字段预览开始:limit=%s", preview_limit)
|
||||||
|
count = 0
|
||||||
|
for job_no, item in ehr_by_job_no.items():
|
||||||
|
emp = item.get("employeeInfo") or {}
|
||||||
|
rec = item.get("recordInfo") or {}
|
||||||
|
if not isinstance(emp, dict):
|
||||||
|
emp = {}
|
||||||
|
if not isinstance(rec, dict):
|
||||||
|
rec = {}
|
||||||
|
|
||||||
|
org_oid = str(rec.get("oIdOrganization") or rec.get("oIdDepartment") or "").strip()
|
||||||
|
org = org_by_oid.get(org_oid, {})
|
||||||
|
company = str((org or {}).get("name") or "")
|
||||||
|
name = str(emp.get("name") or "")
|
||||||
|
rd_attr = _custom_prop_value(rec.get("customProperties"), rd_attr_custom_key) or _custom_prop_value(
|
||||||
|
emp.get("customProperties"), rd_attr_custom_key
|
||||||
|
)
|
||||||
|
place = str(rec.get("place") or "")
|
||||||
|
entry_date = _date_only(rec.get("entryDate"))
|
||||||
|
leave_date = _date_only(rec.get("lastWorkDate")) or "2099-12-31"
|
||||||
|
id_number = str(emp.get("iDNumber") or "")
|
||||||
|
hrbp = str((org or {}).get("hRBP") or "")
|
||||||
|
manager = str(rec.get("pOIdEmpAdmin") or "")
|
||||||
|
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",
|
||||||
|
job_no,
|
||||||
|
company,
|
||||||
|
name,
|
||||||
|
rd_attr,
|
||||||
|
place,
|
||||||
|
entry_date,
|
||||||
|
leave_date,
|
||||||
|
id_number,
|
||||||
|
hrbp,
|
||||||
|
manager,
|
||||||
|
is_leaving,
|
||||||
|
domain_account,
|
||||||
|
)
|
||||||
|
count += 1
|
||||||
|
if count >= preview_limit:
|
||||||
|
break
|
||||||
|
logger.info("EHR 字段预览结束:printed=%s", count)
|
||||||
|
|
||||||
# 4) 导出 OA 表单,建立字段映射 + 工号到记录ID映射
|
# 4) 导出 OA 表单,建立字段映射 + 工号到记录ID映射
|
||||||
exp_resp = seeyon.export_cap4_form_soap(
|
exp_resp = seeyon.export_cap4_form_soap(
|
||||||
|
|
@ -369,8 +402,6 @@ class SyncEhrToOaFormJob(BaseJob):
|
||||||
oa_id_by_job_no: dict[str, int] = {}
|
oa_id_by_job_no: dict[str, int] = {}
|
||||||
oa_id_by_job_no_norm: dict[str, int] = {}
|
oa_id_by_job_no_norm: dict[str, int] = {}
|
||||||
row_parse_miss = 0
|
row_parse_miss = 0
|
||||||
row_id_fallback_count = 0
|
|
||||||
row_id_fallback_samples: list[str] = []
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
if not isinstance(row, dict):
|
if not isinstance(row, dict):
|
||||||
continue
|
continue
|
||||||
|
|
@ -388,30 +419,24 @@ class SyncEhrToOaFormJob(BaseJob):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if row_id is None:
|
if row_id is None:
|
||||||
# 某些 OA export 不返回主键 id;此时依赖 uniqueFiled(工号) 进行更新匹配。
|
row_parse_miss += 1
|
||||||
row_id = 0
|
if verbose_trace and row_parse_miss <= 20:
|
||||||
row_id_fallback_count += 1
|
|
||||||
if len(row_id_fallback_samples) < 20:
|
|
||||||
row_id_fallback_samples.append(job_no)
|
|
||||||
if verbose_trace and row_id_fallback_count <= 20:
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"OA 行解析未取到记录ID,使用回退ID=0:job_no=%s row_keys=%s",
|
"OA 行解析未取到记录ID:job_no=%s row_keys=%s",
|
||||||
job_no,
|
job_no,
|
||||||
list(row.keys())[:20],
|
list(row.keys())[:20],
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
oa_id_by_job_no[job_no] = row_id
|
oa_id_by_job_no[job_no] = row_id
|
||||||
job_no_norm = _normalize_job_no(job_no)
|
job_no_norm = _normalize_job_no(job_no)
|
||||||
if job_no_norm:
|
if job_no_norm:
|
||||||
oa_id_by_job_no_norm[job_no_norm] = row_id
|
oa_id_by_job_no_norm[job_no_norm] = row_id
|
||||||
logger.info(
|
logger.info(
|
||||||
"OA 工号索引完成:indexed_job_numbers=%s indexed_job_numbers_norm=%s parse_miss=%s id_fallback=%s",
|
"OA 工号索引完成:indexed_job_numbers=%s indexed_job_numbers_norm=%s parse_miss=%s",
|
||||||
len(oa_id_by_job_no),
|
len(oa_id_by_job_no),
|
||||||
len(oa_id_by_job_no_norm),
|
len(oa_id_by_job_no_norm),
|
||||||
row_parse_miss,
|
row_parse_miss,
|
||||||
row_id_fallback_count,
|
|
||||||
)
|
)
|
||||||
if row_id_fallback_samples:
|
|
||||||
logger.info("OA 记录ID回退样本(前20):%s", row_id_fallback_samples)
|
|
||||||
if verbose_trace:
|
if verbose_trace:
|
||||||
for job_no, row_id in list(oa_id_by_job_no.items()):
|
for job_no, row_id in list(oa_id_by_job_no.items()):
|
||||||
logger.info("OA 工号索引明细:raw=%s norm=%s row_id=%s", job_no, _normalize_job_no(job_no), row_id)
|
logger.info("OA 工号索引明细:raw=%s norm=%s row_id=%s", job_no, _normalize_job_no(job_no), row_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue