1
0
forked from erp-dev/erp
Files
erpnew/flower/utils/mingdaoyun/relations.py

160 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import json
from typing import Any
from .mappings import plate_order_related_field_definitions, plate_order_relation_control_map
def _json_loads_safe(value: str) -> Any:
try:
return json.loads(value)
except Exception:
return value
def normalize_mdy_value(value: Any) -> Any:
"""尽量把明道云返回的字符串 JSON 规范化为 Python 对象。
常见情况:
- Relation/Attachment 可能返回字符串形式的 "[]" / "[{...}]"
- 空值经常是 "[]"(字符串)
"""
if value is None:
return None
if isinstance(value, str):
s = value.strip()
if s == "[]":
return []
if (s.startswith("[") and s.endswith("]")) or (s.startswith("{") and s.endswith("}")):
return _json_loads_safe(s)
return value
return value
def extract_relation_rowids(value: Any) -> list[str]:
"""从 Relation 字段的 value 中提取 rowid 列表。
兼容形态:
- list[dict](常见:[{rowid,name,link}, ...]
- str可能是 JSON 字符串数组,如 "[{...}]""[]";也可能是逗号分割 rowId
- dict单条
"""
value = normalize_mdy_value(value)
if value is None:
return []
if isinstance(value, list):
out: list[str] = []
for item in value:
if isinstance(item, dict):
rid = item.get("rowid") or item.get("rowId")
if rid:
out.append(str(rid))
elif isinstance(item, str) and item.strip():
out.append(item.strip())
return out
if isinstance(value, dict):
rid = value.get("rowid") or value.get("rowId")
return [str(rid)] if rid else []
if isinstance(value, str):
s = value.strip()
if not s or s == "[]":
return []
# 兜底:逗号分割
return [x for x in (p.strip() for p in s.split(",")) if x]
return []
def extract_plate_order_related_rowids(plate_order_row: dict[str, Any]) -> dict[str, list[str]]:
"""从开版主表行记录中提取各关联表的 rowid 列表。
返回:
- {related_key: [rowid, ...], ...}
"""
result: dict[str, list[str]] = {}
for control_id, related_key in plate_order_relation_control_map.items():
rowids = extract_relation_rowids(plate_order_row.get(control_id))
if rowids:
result[related_key] = rowids
return result
def flatten_row_by_field_definitions(
row: dict[str, Any],
field_definitions: dict[str, dict[str, Any]],
*,
drop_types: set[str] | None = None,
drop_names: set[str] | None = None,
include_system_keys: bool = True,
) -> dict[str, Any]:
"""按字段定义把一条明道云 row 转成“可读 dict”。
- key 使用字段中文名(若缺失则回退 controlId
- value 做一定的 JSON 字符串规范化
- 默认包含系统字段rowid/ctime/utime若存在
"""
drop_types = drop_types or set()
drop_names = drop_names or set()
out: dict[str, Any] = {}
if include_system_keys:
for k in ("rowid", "ctime", "utime"):
if k in row:
out[k] = row.get(k)
for field_id, meta in field_definitions.items():
name = meta.get("name") or field_id
ftype = meta.get("type")
if ftype in drop_types:
continue
if name in drop_names:
continue
out[name] = normalize_mdy_value(row.get(field_id))
return out
def flatten_plate_order_related_row(related_key: str, related_row: dict[str, Any]) -> dict[str, Any]:
"""将开版关联表的一条 row 扁平化为 dict用于入库 staging.related
- 自动删除回溯 Relation 字段(开版管理/开发管理等)
- 保留 rowid/ctime/utime若存在
- 额外写入 source 信息,便于排查
"""
meta = plate_order_related_field_definitions.get(related_key) or {}
wsid = meta.get("worksheet_id")
cn_name = meta.get("name")
fields = meta.get("fields") or {}
flat = flatten_row_by_field_definitions(
related_row,
fields,
drop_types={"Relation"},
drop_names={"开版管理", "开发管理"},
include_system_keys=True,
)
# 扁平化结构:[{key: val}, ...] 里的每个元素是一条记录
flat["source"] = related_key
if cn_name:
flat["source_name"] = cn_name
if wsid:
flat["worksheet_id"] = wsid
return flat