forked from erp-dev/erp
226 lines
6.9 KiB
Python
226 lines
6.9 KiB
Python
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):
|
||
return rows[0]
|
||
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}")
|