56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Shared helpers for ODS/API record normalization."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Iterable
|
|
|
|
|
|
def merge_record_layers(record: dict) -> dict:
|
|
"""Flatten nested data/settleList layers into a single dict."""
|
|
merged = record
|
|
data_part = merged.get("data")
|
|
while isinstance(data_part, dict):
|
|
merged = {**data_part, **merged}
|
|
data_part = data_part.get("data")
|
|
settle_inner = merged.get("settleList")
|
|
if isinstance(settle_inner, dict):
|
|
merged = {**settle_inner, **merged}
|
|
return merged
|
|
|
|
|
|
def get_value_case_insensitive(record: dict | None, col: str | None):
|
|
"""Fetch column value without case sensitivity."""
|
|
if record is None or col is None:
|
|
return None
|
|
if col in record:
|
|
return record.get(col)
|
|
col_lower = col.lower()
|
|
for k, v in record.items():
|
|
if isinstance(k, str) and k.lower() == col_lower:
|
|
return v
|
|
return None
|
|
|
|
|
|
def normalize_pk_value(value):
|
|
"""Normalize PK value (e.g., digit string -> int)."""
|
|
if value is None:
|
|
return None
|
|
if isinstance(value, str) and value.isdigit():
|
|
try:
|
|
return int(value)
|
|
except Exception:
|
|
return value
|
|
return value
|
|
|
|
|
|
def pk_tuple_from_record(record: dict, pk_cols: Iterable[str]) -> tuple | None:
|
|
"""Extract PK tuple from a record."""
|
|
merged = merge_record_layers(record)
|
|
values = []
|
|
for col in pk_cols:
|
|
val = normalize_pk_value(get_value_case_insensitive(merged, col))
|
|
if val is None or val == "":
|
|
return None
|
|
values.append(val)
|
|
return tuple(values)
|