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

@@ -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",

View File

@@ -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

View File

@@ -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
# )

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