From 1a37bdf387f92b5ecaca440ad8c42d9545760e3f Mon Sep 17 00:00:00 2001 From: Marsway Date: Wed, 25 Mar 2026 10:25:53 +0800 Subject: [PATCH] update --- extensions/sync_ehr_to_oa/job.py | 36 ++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/extensions/sync_ehr_to_oa/job.py b/extensions/sync_ehr_to_oa/job.py index f00549a..db5a1f3 100644 --- a/extensions/sync_ehr_to_oa/job.py +++ b/extensions/sync_ehr_to_oa/job.py @@ -436,16 +436,26 @@ class SyncEhrToOaFormJob(BaseJob): # 从 export 中提取“工号 -> 字段值字典”,用于值兜底(避免把已有值覆盖为空) 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: if not isinstance(row, dict): 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_no = _cell_value(job_cell) norm = _normalize_job_no(job_no) if norm: 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 记录ID索引完成:raw=%s norm=%s", + len(export_id_by_job_no), + len(export_id_by_job_no_norm), + ) job_field_code = display_to_code["工号"] 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_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: - 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) # 5) 组装批量更新数据 @@ -476,10 +504,10 @@ class SyncEhrToOaFormJob(BaseJob): not_found_in_oa = 0 unmatched_samples: list[str] = [] 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" 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" if oa_record_id is None: not_found_in_oa += 1