This commit is contained in:
Marsway 2026-03-25 10:25:53 +08:00
parent ae6d323ff8
commit 1a37bdf387
1 changed files with 32 additions and 4 deletions

View File

@ -436,16 +436,26 @@ class SyncEhrToOaFormJob(BaseJob):
# 从 export 中提取“工号 -> 字段值字典”,用于值兜底(避免把已有值覆盖为空) # 从 export 中提取“工号 -> 字段值字典”,用于值兜底(避免把已有值覆盖为空)
oa_fields_by_job_no_norm: dict[str, dict[str, Any]] = {} oa_fields_by_job_no_norm: dict[str, dict[str, Any]] = {}
export_id_by_job_no: dict[str, int] = {}
export_id_by_job_no_norm: dict[str, int] = {}
for row in rows: for row in rows:
if not isinstance(row, dict): if not isinstance(row, dict):
continue continue
_rid, field_map = _extract_oa_row_id_and_fields(row) rid, field_map = _extract_oa_row_id_and_fields(row)
job_cell = field_map.get(display_to_code["工号"]) job_cell = field_map.get(display_to_code["工号"])
job_no = _cell_value(job_cell) job_no = _cell_value(job_cell)
norm = _normalize_job_no(job_no) norm = _normalize_job_no(job_no)
if norm: if norm:
oa_fields_by_job_no_norm[norm] = field_map oa_fields_by_job_no_norm[norm] = field_map
if rid is not None:
export_id_by_job_no[job_no] = rid
export_id_by_job_no_norm[norm] = rid
logger.info("OA export 字段值索引完成rows=%s indexed_by_job_no=%s", len(rows), len(oa_fields_by_job_no_norm)) logger.info("OA export 字段值索引完成rows=%s indexed_by_job_no=%s", len(rows), len(oa_fields_by_job_no_norm))
logger.info(
"OA export 记录ID索引完成raw=%s norm=%s",
len(export_id_by_job_no),
len(export_id_by_job_no_norm),
)
job_field_code = display_to_code["工号"] job_field_code = display_to_code["工号"]
oa_id_by_job_no: dict[str, int] = {} oa_id_by_job_no: dict[str, int] = {}
@ -467,8 +477,26 @@ class SyncEhrToOaFormJob(BaseJob):
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),
) )
# 关键修复:优先使用 export 的 record.id与 batch-update 同源SQL 仅兜底。
merged_id_by_job_no = dict(oa_id_by_job_no)
merged_id_by_job_no_norm = dict(oa_id_by_job_no_norm)
merged_id_by_job_no.update(export_id_by_job_no)
merged_id_by_job_no_norm.update(export_id_by_job_no_norm)
logger.info(
"OA 工号索引合并完成export 优先, SQL 兜底raw=%s norm=%s",
len(merged_id_by_job_no),
len(merged_id_by_job_no_norm),
)
# 记录 ID 冲突样本,便于确认 SQL 与 export 是否来自同一数据源
id_conflict_samples: list[tuple[str, int, int]] = []
for k, export_id in export_id_by_job_no.items():
sql_id = oa_id_by_job_no.get(k)
if sql_id is not None and sql_id != export_id and len(id_conflict_samples) < 20:
id_conflict_samples.append((k, sql_id, export_id))
if id_conflict_samples:
logger.warning("OA 记录ID冲突样本job_no, sql_id, export_id=%s", id_conflict_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(merged_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)
# 5) 组装批量更新数据 # 5) 组装批量更新数据
@ -476,10 +504,10 @@ class SyncEhrToOaFormJob(BaseJob):
not_found_in_oa = 0 not_found_in_oa = 0
unmatched_samples: list[str] = [] unmatched_samples: list[str] = []
for job_no, item in ehr_by_job_no.items(): for job_no, item in ehr_by_job_no.items():
oa_record_id = oa_id_by_job_no.get(job_no) oa_record_id = merged_id_by_job_no.get(job_no)
matched_by = "raw" matched_by = "raw"
if oa_record_id is None: if oa_record_id is None:
oa_record_id = oa_id_by_job_no_norm.get(_normalize_job_no(job_no)) oa_record_id = merged_id_by_job_no_norm.get(_normalize_job_no(job_no))
matched_by = "normalized" matched_by = "normalized"
if oa_record_id is None: if oa_record_id is None:
not_found_in_oa += 1 not_found_in_oa += 1