1
0
forked from erp-dev/erp
Files

231 lines
7.2 KiB
Python
Raw Permalink 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
from typing import Any
from asgiref.sync import sync_to_async
from .client import MDY_ENDPOINT_GET_FILTER_ROWS, get_default_mingdaoyun_client
from .mappings import (
MDY_WORKSHEET_ID_CUSTOMER,
MDY_WORKSHEET_ID_FABRIC,
MDY_WORKSHEET_ID_PLATE_ORDER,
MDY_WORKSHEET_ID_PRODUCT,
)
from .models import Customer, Fabric, Product
from .parsers import pick_customer, pick_fabric, pick_product
async def fetch_products_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Product], int]:
"""从明道云获取产品列表"""
client = get_default_mingdaoyun_client()
response = await client.post(
endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
data={
"worksheetId": MDY_WORKSHEET_ID_PRODUCT,
"pageIndex": page,
"pageSize": page_size,
"sortId": "ctime",
"isAsc": True,
},
)
data = response.get("data") if isinstance(response, dict) else None
if data:
print(
f'[product-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
)
else:
print(f"[product-sync] page={page} size={page_size} received empty data")
if not data:
return [], 0
products = [pick_product(item) for item in data.get("rows", [])]
total_count = data.get("total", 0)
return products, total_count
async def fetch_customers_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Customer], int]:
"""从明道云获取客户列表"""
client = get_default_mingdaoyun_client()
response = await client.post(
endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
data={
"worksheetId": MDY_WORKSHEET_ID_CUSTOMER,
"pageIndex": page,
"pageSize": page_size,
"sortId": "ctime",
"isAsc": True,
},
)
data = response.get("data") if isinstance(response, dict) else None
if data:
print(
f'[customer-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
)
else:
print(f"[customer-sync] page={page} size={page_size} received empty data")
if not data:
return [], 0
customers = [pick_customer(item) for item in data.get("rows", [])]
total_count = data.get("total", 0)
return customers, total_count
async def fetch_row_by_rowid_from_mingdaoyun(
worksheet_id: str,
rowid: str,
*,
sort_id: str = "ctime",
is_asc: bool = False,
list_type: int = 1,
not_get_total: bool = True,
data_type: int = 2,
filter_type: int = 3,
control_id: str = "rowId",
) -> dict[str, Any] | None:
"""按 rowId 查询工作表的单条记录(仅封装 rowId 等值查询)。
按照明道云 getFilterRows 的 filters 结构构造请求:
- dataType=2 表示字符串
- filterType=3 表示“相等”
返回:
- 匹配到记录:返回第一条 row dict
- 未匹配或响应无 data返回 None
"""
client = get_default_mingdaoyun_client()
response = await client.post(
endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
data={
"worksheetId": worksheet_id,
"listType": list_type,
"sortId": sort_id,
"isAsc": is_asc,
"notGetTotal": not_get_total,
"filters": [
{
"controlId": control_id,
"dataType": data_type,
"filterType": filter_type,
"value": rowid,
}
],
},
)
data = response.get("data") if isinstance(response, dict) else None
if not data:
return None
rows = data.get("rows") or []
if not rows:
return None
if isinstance(rows[0], dict):
first = rows[0]
# 明道云在 filters 不合法/不生效时可能仍返回默认列表数据。
# 这里做一次校验,避免“误返回不匹配的第一条记录”。
if first.get("rowid") != rowid:
return None
return first
return None
async def fetch_plate_orders_from_mingdaoyun(
page: int = 1,
page_size: int = 100,
*,
sort_id: str = "ctime",
is_asc: bool = True,
) -> tuple[list[dict[str, Any]], int]:
"""从明道云获取“开版数据表”记录列表(原始行字典,不做字段映射解析)"""
client = get_default_mingdaoyun_client()
response = await client.post(
endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
data={
"worksheetId": MDY_WORKSHEET_ID_PLATE_ORDER,
"pageIndex": page,
"pageSize": page_size,
"sortId": sort_id,
"isAsc": is_asc,
},
)
data = response.get("data") if isinstance(response, dict) else None
if data:
print(
f'[plate-order-fetch] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
)
else:
print(f"[plate-order-fetch] page={page} size={page_size} received empty data")
if not data:
return [], 0
rows = data.get("rows", [])
total_count = data.get("total", 0)
return rows, total_count
async def sync_fabric_from_mingdaoyun(page: int = 1, page_size: int = 100) -> int:
"""从明道云同步面料数据(用于创建/更新 QuickInput: 布料名)"""
client = get_default_mingdaoyun_client()
response = await client.post(
endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
data={
"worksheetId": MDY_WORKSHEET_ID_FABRIC,
"pageIndex": page,
"pageSize": page_size,
"sortId": "ctime",
"isAsc": False,
},
)
data = response.get("data") if isinstance(response, dict) else None
if data:
rows = data.get("rows", [])
print(f"[fabric-sync] fetch rows={len(rows)} total={data.get('total')}")
if rows:
print(f"[fabric-sync] first row keys: {list(rows[0].keys())[:10]}")
print(f"[fabric-sync] first row sample: {rows[0]}")
else:
print(f"[fabric-sync] fetch empty data (page={page}, size={page_size})")
if not data:
return 0
fabrics = [pick_fabric(item) for item in data.get("rows", [])]
total_count = data.get("total", 0)
await sync_to_async(_create_fabric_quick_inputs)(
page,
page_size,
fabrics,
)
return total_count
def _create_fabric_quick_inputs(page: int, page_size: int, fabrics: list[Fabric]) -> None:
from basic_info import models as basic_models
total = len(fabrics)
created_count = 0
sample_names = [fabric.name for fabric in fabrics[:5]]
print(f"[fabric-sync] page={page} size={page_size} fetched={total}")
print(f"[fabric-sync] sample names: {sample_names}")
for fabric in fabrics:
if not fabric.name:
continue
obj, created = basic_models.QuickInput.objects.update_or_create(
name=fabric.name,
group="布料名",
defaults={"value": fabric.name},
)
if created:
created_count += 1
print(f"[fabric-sync] page={page} new_records={created_count} updated_or_existing={total - created_count}")