forked from erp-dev/erp
feat: batch update for plate order
This commit is contained in:
159
flower/utils/mingdaoyun/relations.py
Normal file
159
flower/utils/mingdaoyun/relations.py
Normal file
@@ -0,0 +1,159 @@
|
||||
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
|
||||
Reference in New Issue
Block a user