This commit is contained in:
Marsway 2026-03-30 17:19:14 +08:00
parent 96b3439c5b
commit 6c804b7b84
1 changed files with 94 additions and 2 deletions

View File

@ -80,6 +80,66 @@ def _to_int_safe(v: Any) -> int:
return 0 return 0
def _cell_value(cell: Any) -> str:
if isinstance(cell, dict):
v = cell.get("value")
if v is None or str(v).strip() == "":
v = cell.get("showValue")
return str(v or "").strip()
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 _extract_oa_row_id_and_fields(row: dict[str, Any]) -> tuple[int | None, dict[str, Any]]:
field_map: dict[str, Any] = {}
row_id: int | None = None
master = row.get("masterData")
if isinstance(master, dict):
for k, v in master.items():
if isinstance(k, str) and k.startswith("field"):
field_map[k] = v
for candidate in (row.get("id"), row.get("masterDataId"), master.get("id")):
if candidate is None:
continue
rid = _to_int_safe(candidate)
if rid > 0:
row_id = rid
break
master_table = row.get("masterTable")
if isinstance(master_table, dict):
record = master_table.get("record")
if isinstance(record, dict):
fields = record.get("fields")
if isinstance(fields, list):
for fld in fields:
if not isinstance(fld, dict):
continue
name = str(fld.get("name") or "").strip()
if name:
field_map[name] = fld
if row_id is None:
rid = _to_int_safe(record.get("id"))
if rid > 0:
row_id = rid
row_fields = row.get("fields")
if isinstance(row_fields, list):
for fld in row_fields:
if not isinstance(fld, dict):
continue
name = str(fld.get("name") or "").strip()
if name:
field_map[name] = fld
return row_id, field_map
def _normalize_decimal_1(v: Any) -> str: def _normalize_decimal_1(v: Any) -> str:
return _decimal_to_str(_to_decimal(v)) return _decimal_to_str(_to_decimal(v))
@ -207,6 +267,9 @@ class SyncEhrLeavesToOaMonthJob(BaseJob):
field_leave_days = display_to_code[display_leave_days] field_leave_days = display_to_code[display_leave_days]
field_name = display_to_code.get(display_name) field_name = display_to_code.get(display_name)
master_table_name = _OA_SQLSERVER_TABLE master_table_name = _OA_SQLSERVER_TABLE
rows = form.get("data") or []
if not isinstance(rows, list):
rows = []
vacations = ehr.get_vacations_in_date_range( vacations = ehr.get_vacations_in_date_range(
start_date=month_start, start_date=month_start,
@ -270,7 +333,32 @@ class SyncEhrLeavesToOaMonthJob(BaseJob):
if staff_name and key not in name_map: if staff_name and key not in name_map:
name_map[key] = staff_name name_map[key] = staff_name
existing_row_map = ehr.get_oa_rows_by_job_and_date( existing_row_map_by_export: dict[tuple[str, str], dict[str, str]] = {}
for row in rows:
if not isinstance(row, dict):
continue
rid, field_map = _extract_oa_row_id_and_fields(row)
job_no = _cell_value(field_map.get(field_job_no))
leave_date = _cell_show_value(field_map.get(field_leave_date)) or _date_only(_cell_value(field_map.get(field_leave_date)))
if not job_no or not leave_date:
continue
leave_days_val = _cell_value(field_map.get(field_leave_days))
name_val = _cell_value(field_map.get(field_name)) if field_name else ""
existing_row_map_by_export[(job_no, leave_date)] = {
"id": str(rid or ""),
"job_no": job_no,
"leave_date": leave_date,
"leave_days": leave_days_val,
"name": name_val,
}
logger.info(
"OA export 现有记录索引完成month=%s~%s indexed=%s",
month_start.isoformat(),
month_end.isoformat(),
len(existing_row_map_by_export),
)
existing_row_map_by_sql = ehr.get_oa_rows_by_job_and_date(
table_name=_OA_SQLSERVER_TABLE, table_name=_OA_SQLSERVER_TABLE,
schema=_OA_SQLSERVER_SCHEMA, schema=_OA_SQLSERVER_SCHEMA,
job_no_column=field_job_no, job_no_column=field_job_no,
@ -280,6 +368,9 @@ class SyncEhrLeavesToOaMonthJob(BaseJob):
start_date=month_start, start_date=month_start,
end_date=month_end, end_date=month_end,
) )
# 以 export 为主(日期 showValue 更稳定SQL 兜底补齐
existing_row_map = dict(existing_row_map_by_sql)
existing_row_map.update(existing_row_map_by_export)
data_list: list[dict[str, Any]] = [] data_list: list[dict[str, Any]] = []
to_update = 0 to_update = 0
@ -382,13 +473,14 @@ class SyncEhrLeavesToOaMonthJob(BaseJob):
failed_data[str(k)] = str(v) failed_data[str(k)] = str(v)
logger.info( logger.info(
"EHR 请假月度同步完成month=%s~%s vacations=%s aggregated=%s to_update=%s to_insert=%s success=%s failed=%s", "EHR 请假月度同步完成month=%s~%s vacations=%s aggregated=%s to_update=%s to_insert=%s skipped_unchanged=%s success=%s failed=%s",
month_start.isoformat(), month_start.isoformat(),
month_end.isoformat(), month_end.isoformat(),
len(vacations), len(vacations),
len(agg), len(agg),
to_update, to_update,
to_insert, to_insert,
skipped_unchanged,
success_count, success_count,
failed_count, failed_count,
) )