forked from erp-dev/erp
feat: batch update for plate order
This commit is contained in:
@@ -29,8 +29,10 @@ from .mappings import (
|
||||
fabric_type_map,
|
||||
mdy_table_map,
|
||||
plate_order_field_definitions,
|
||||
plate_order_related_field_definitions,
|
||||
plate_order_related_worksheet_map,
|
||||
plate_order_related_worksheet_map_cn,
|
||||
plate_order_relation_control_map,
|
||||
plate_order_type_map,
|
||||
product_type_map,
|
||||
)
|
||||
@@ -45,6 +47,13 @@ from .models import (
|
||||
ProductListResponse,
|
||||
)
|
||||
from .parsers import pick_customer, pick_fabric, pick_product
|
||||
from .relations import (
|
||||
extract_plate_order_related_rowids,
|
||||
extract_relation_rowids,
|
||||
flatten_plate_order_related_row,
|
||||
flatten_row_by_field_definitions,
|
||||
normalize_mdy_value,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# client
|
||||
@@ -71,8 +80,10 @@ __all__ = [
|
||||
"customer_type_map",
|
||||
"fabric_type_map",
|
||||
"plate_order_field_definitions",
|
||||
"plate_order_related_field_definitions",
|
||||
"plate_order_related_worksheet_map",
|
||||
"plate_order_related_worksheet_map_cn",
|
||||
"plate_order_relation_control_map",
|
||||
"plate_order_type_map",
|
||||
# models
|
||||
"Product",
|
||||
@@ -87,6 +98,12 @@ __all__ = [
|
||||
"pick_product",
|
||||
"pick_customer",
|
||||
"pick_fabric",
|
||||
# relations / flatten utils
|
||||
"normalize_mdy_value",
|
||||
"extract_relation_rowids",
|
||||
"extract_plate_order_related_rowids",
|
||||
"flatten_row_by_field_definitions",
|
||||
"flatten_plate_order_related_row",
|
||||
# fetch
|
||||
"fetch_products_from_mingdaoyun",
|
||||
"fetch_customers_from_mingdaoyun",
|
||||
|
||||
@@ -126,7 +126,12 @@ async def fetch_row_by_rowid_from_mingdaoyun(
|
||||
if not rows:
|
||||
return None
|
||||
if isinstance(rows[0], dict):
|
||||
return rows[0]
|
||||
first = rows[0]
|
||||
# 明道云在 filters 不合法/不生效时可能仍返回默认列表数据。
|
||||
# 这里做一次校验,避免“误返回不匹配的第一条记录”。
|
||||
if first.get("rowid") != rowid:
|
||||
return None
|
||||
return first
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -45,6 +45,158 @@ plate_order_related_worksheet_map_cn = {
|
||||
"照图开发": MDY_WORKSHEET_ID_PLATE_ORDER_IMAGE_DEVELOPMENT,
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 明道云:开版相关“关联表”字段映射(用于后续关联查询/解析)
|
||||
#
|
||||
# 说明:
|
||||
# - 这里记录的是“字段 controlId -> 字段含义/类型/备注”。
|
||||
# - Relation(29) 字段在写入时通常按文档要求使用 rowId 字符串(多条用逗号分割、全量覆盖),
|
||||
# 但 getFilterRows 拉取时返回结构可能是 list[{"rowid","name","link"}],解析时需兼容两种形态。
|
||||
# ------------------------------------------------------------------------------
|
||||
plate_order_related_field_definitions: Dict[str, Dict[str, Any]] = {
|
||||
# 1) 画图
|
||||
"drawing": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_DRAWING,
|
||||
"name": "画图",
|
||||
"fields": {
|
||||
"62d7f09ad55983029b644b25": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492dda0": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492dd9b": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"6412d650120c799be027953d": {
|
||||
"name": "开版管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
"62d52f4b8d2972284492dd9d": {
|
||||
"name": "开发管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
},
|
||||
},
|
||||
# 2) 调色
|
||||
"coloring": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_COLORING,
|
||||
"name": "调色",
|
||||
"fields": {
|
||||
"62d7f0c2d121077a8492619d": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492dda8": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492dda3": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"6716620b985d1a2af61776b5": {
|
||||
"name": "完成数量",
|
||||
"type": "Number",
|
||||
"note": "Double(例如 666.66)",
|
||||
},
|
||||
"62d52f4b8d2972284492dda5": {
|
||||
"name": "开发管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
},
|
||||
},
|
||||
# 3) 套纸样
|
||||
"pattern_set": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_PATTERN_SET,
|
||||
"name": "套纸样",
|
||||
"fields": {
|
||||
"62d7f0cfa72269e1965389e7": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492de8c": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492de89": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"671661bc8d15ca93fdec7e5f": {
|
||||
"name": "完成数量",
|
||||
"type": "Number",
|
||||
"note": "Double(例如 666.66)",
|
||||
},
|
||||
"62d52f4b8d2972284492de8d": {
|
||||
"name": "开版管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
},
|
||||
},
|
||||
# 4) 改图
|
||||
"modify_drawing": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_MODIFY_DRAWING,
|
||||
"name": "改图",
|
||||
"fields": {
|
||||
"62d7f0cfa72269e1965389e7": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492de8c": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492de89": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"66e2ebb7da66655f355bf709": {
|
||||
"name": "开版管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
},
|
||||
},
|
||||
# 5) 配色
|
||||
"color_scheme": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_COLOR_SCHEME,
|
||||
"name": "配色",
|
||||
"fields": {
|
||||
"62d7f09ad55983029b644b25": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492dda0": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492dd9b": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"672adc9b156abb9a08ab2a61": {
|
||||
"name": "开版管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
# 注:配色表无“完成数量”,用“开发数量”替代
|
||||
"66e2ef8d99632ae7376e73ef": {
|
||||
"name": "开发数量",
|
||||
"type": "Number",
|
||||
"note": "Double(例如 666.66)",
|
||||
},
|
||||
},
|
||||
},
|
||||
# 6) 找图开发(照图开发)
|
||||
"image_development": {
|
||||
"worksheet_id": MDY_WORKSHEET_ID_PLATE_ORDER_IMAGE_DEVELOPMENT,
|
||||
"name": "找图开发",
|
||||
"fields": {
|
||||
"62d7f09ad55983029b644b25": {"name": "设计师名字", "type": "Text"},
|
||||
"62d52f4b8d2972284492dda0": {"name": "电脑位置", "type": "Text"},
|
||||
"62d52f4b8d2972284492dd9b": {
|
||||
"name": "附件",
|
||||
"type": "Attachment",
|
||||
"note": "json,支持外部链接和 Base64 文件流",
|
||||
},
|
||||
"66e2efb0da66655f355bf963": {
|
||||
"name": "开版管理",
|
||||
"type": "Relation",
|
||||
"note": "String 字符串,多条记录 rowId 用(,)分割,全量覆盖操作",
|
||||
},
|
||||
# 注:找图开发表无“完成数量”,用“开发数量”替代
|
||||
"66e2ef8d99632ae7376e73ef": {
|
||||
"name": "开发数量",
|
||||
"type": "Number",
|
||||
"note": "Double(例如 666.66)",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 明道云:字段映射(内部字段名 -> controlId)
|
||||
@@ -165,3 +317,19 @@ plate_order_type_map = {
|
||||
"created_at": "ctime",
|
||||
"rowid": "rowid",
|
||||
}
|
||||
|
||||
# PlateOrder 行中“关联字段 controlId -> 关联表 key”
|
||||
# 用于从开版主表记录中提取跨表 rowid 并进一步查询关联表数据。
|
||||
plate_order_relation_control_map = {
|
||||
plate_order_type_map["drawing_relation"]: "drawing",
|
||||
plate_order_type_map["color_relation"]: "coloring",
|
||||
plate_order_type_map["pattern_set"]: "pattern_set",
|
||||
plate_order_type_map["modify_drawing_relation"]: "modify_drawing",
|
||||
plate_order_type_map["color_scheme_relation"]: "color_scheme",
|
||||
plate_order_type_map["image_development_relation"]: "image_development",
|
||||
}
|
||||
|
||||
# json key 查询
|
||||
# MDYPlateOrderStaging.objects.filter(
|
||||
# raw__62d52f4b8d2972284492dd0e="82724" # 设计编号/订单id(明道云字段ID)
|
||||
# )
|
||||
|
||||
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