1
0
forked from erp-dev/erp

feat: batch update for plate order

This commit is contained in:
2025-12-18 17:36:43 +08:00
parent 98d797221a
commit 1a6ce32441
33 changed files with 32087 additions and 8 deletions

View 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