forked from erp-dev/erp
284 lines
7.3 KiB
Python
284 lines
7.3 KiB
Python
import aiohttp
|
||
from typing import Optional, Dict, Any, List
|
||
from pydantic import BaseModel, Field, computed_field
|
||
from enum import Enum
|
||
import json
|
||
|
||
|
||
class Product(BaseModel):
|
||
"""产品模型 - 请在此填入你的字段"""
|
||
uid: str
|
||
rowid: str
|
||
name: str
|
||
unit: str | None
|
||
color: str | None
|
||
width: str | None = None
|
||
detail_str: str | None = Field(exclude=True) # 在序列化时排除此字段
|
||
created_at: str
|
||
|
||
@computed_field
|
||
@property
|
||
def detail(self) -> dict[str, Any]:
|
||
"""将 detail_str 转换为字典"""
|
||
try:
|
||
return json.loads(self.detail_str) if self.detail_str else {}
|
||
except (json.JSONDecodeError, TypeError):
|
||
return {}
|
||
|
||
|
||
class ProductListResponse(BaseModel):
|
||
"""产品列表响应"""
|
||
products: List[Product]
|
||
total: int
|
||
|
||
|
||
mdy_table_map = {
|
||
'product': 'spmx',
|
||
'customer': 'quanbu',
|
||
}
|
||
|
||
|
||
class HTTPMethod(Enum):
|
||
"""HTTP 请求方法枚举"""
|
||
GET = "GET"
|
||
POST = "POST"
|
||
|
||
|
||
class MingDaoYunClient:
|
||
"""明道云 API 客户端"""
|
||
|
||
def __init__(self, app_key: str, sign: str, base_url: str = ""):
|
||
"""
|
||
初始化客户端
|
||
|
||
Args:
|
||
app_key: 应用密钥
|
||
sign: 签名
|
||
base_url: API 基础地址
|
||
"""
|
||
self.app_key = app_key
|
||
self.sign = sign
|
||
self.base_url = base_url
|
||
|
||
async def request(
|
||
self,
|
||
method: HTTPMethod,
|
||
endpoint: str,
|
||
data: Optional[Dict[str, Any]] = None,
|
||
params: Optional[Dict[str, Any]] = None,
|
||
headers: Optional[Dict[str, str]] = None,
|
||
) -> Any:
|
||
"""
|
||
通用异步请求函数
|
||
|
||
Args:
|
||
method: 请求方法 (GET/POST)
|
||
endpoint: API 端点路径
|
||
data: POST 请求体数据(JSON)
|
||
params: URL 查询参数
|
||
headers: 自定义请求头
|
||
|
||
Returns:
|
||
响应 JSON 数据
|
||
|
||
Raises:
|
||
aiohttp.ClientError: 请求失败时抛出
|
||
"""
|
||
url = f"{self.base_url}{endpoint}"
|
||
|
||
# 构建默认请求头
|
||
default_headers = {
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
if headers:
|
||
default_headers.update(headers)
|
||
|
||
# 添加认证参数
|
||
auth_params = {
|
||
"appKey": self.app_key,
|
||
"sign": self.sign
|
||
}
|
||
|
||
async with aiohttp.ClientSession() as session:
|
||
if method == HTTPMethod.GET:
|
||
async with session.get(url, params=params, json=auth_params) as response:
|
||
response.raise_for_status()
|
||
return await response.json()
|
||
|
||
elif method == HTTPMethod.POST:
|
||
if data is None:
|
||
data = {}
|
||
|
||
data.update(auth_params)
|
||
async with session.post(url, json=data) as response:
|
||
response.raise_for_status()
|
||
return await response.json()
|
||
|
||
else:
|
||
raise ValueError(f"Unsupported HTTP method: {method}")
|
||
|
||
async def get(
|
||
self,
|
||
endpoint: str,
|
||
params: Optional[Dict[str, Any]] = None,
|
||
headers: Optional[Dict[str, str]] = None,
|
||
) -> Any:
|
||
"""
|
||
发送 GET 请求
|
||
|
||
Args:
|
||
endpoint: API 端点路径
|
||
params: URL 查询参数
|
||
headers: 自定义请求头
|
||
|
||
Returns:
|
||
响应 JSON 数据
|
||
"""
|
||
return await self.request(
|
||
method=HTTPMethod.GET,
|
||
endpoint=endpoint,
|
||
params=params,
|
||
headers=headers,
|
||
)
|
||
|
||
async def post(
|
||
self,
|
||
endpoint: str,
|
||
data: Optional[Dict[str, Any]] = None,
|
||
params: Optional[Dict[str, Any]] = None,
|
||
headers: Optional[Dict[str, str]] = None,
|
||
) -> Any:
|
||
"""
|
||
发送 POST 请求
|
||
|
||
Args:
|
||
endpoint: API 端点路径
|
||
data: POST 请求体数据(JSON)
|
||
params: URL 查询参数
|
||
headers: 自定义请求头
|
||
|
||
Returns:
|
||
响应 JSON 数据
|
||
"""
|
||
return await self.request(
|
||
method=HTTPMethod.POST,
|
||
endpoint=endpoint,
|
||
data=data,
|
||
params=params,
|
||
headers=headers,
|
||
)
|
||
|
||
|
||
product_type_map = {
|
||
'name': '668caa5eb80969563ecaee7d',
|
||
'color': '66ed3b9ae01d5599bdb45f6d',
|
||
'uid': '668caa5eb80969563ecaee7c',
|
||
'unit': '668e2ee2ca758c8cc5d0dc1d',
|
||
'width': '668e2194790c0e04058b4f3c',
|
||
'detail_str': '668caa5eb80969563ecaee7e',
|
||
'created_at': 'ctime',
|
||
'rowid': 'rowid',
|
||
}
|
||
|
||
customer_type_map = {
|
||
'name': '62d52f4b8d2972284492dcf9',
|
||
'area': '62d52f4b8d2972284492dd09',
|
||
'created_at': 'ctime',
|
||
'rowid': 'rowid',
|
||
'uid': '668bb9370207cf7520fe551e',
|
||
}
|
||
|
||
class Customer(BaseModel):
|
||
"""客户模型 - 请在此填入你的字段"""
|
||
uid: str
|
||
rowid: str
|
||
name: str
|
||
area: str | None
|
||
created_at: str
|
||
|
||
|
||
def pick_customer(fields: dict) -> Customer:
|
||
"""从字段字典中提取客户信息"""
|
||
data = {k: fields.get(v, '') for k, v in customer_type_map.items()}
|
||
return Customer(**data)
|
||
|
||
|
||
# json param example:
|
||
# {
|
||
# "appKey": "208e55fea5cea59f",
|
||
# "sign": "MWU0YmViYjkwZmM1ZDIzYzRiN2U3ZGQ4MmE4ZGNkMjc0MWM1ZmQ2ZjkwMjljODE4YmNkZTBhMzA0OTU2YzE2NA==",
|
||
# "worksheetId": "quanbu",
|
||
# "listType": 1,
|
||
# "sortId": "ctime",
|
||
# "isAsc": false,
|
||
# "notGetTotal": true
|
||
# }
|
||
|
||
|
||
def pick_product(fields: dict) -> Product:
|
||
"""
|
||
从字段字典中提取产品信息
|
||
"""
|
||
data = {k: fields.get(v, '') for k, v in product_type_map.items()}
|
||
return Product(**data)
|
||
|
||
|
||
async def fetch_products_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Product], int]:
|
||
"""
|
||
从明道云获取产品列表
|
||
|
||
Returns:
|
||
tuple: (产品列表, 总数量)
|
||
"""
|
||
client = MingDaoYunClient(
|
||
app_key='208e55fea5cea59f',
|
||
sign='MWU0YmViYjkwZmM1ZDIzYzRiN2U3ZGQ4MmE4ZGNkMjc0MWM1ZmQ2ZjkwMjljODE4YmNkZTBhMzA0OTU2YzE2NA==',
|
||
base_url="https://api.mingdao.com"
|
||
)
|
||
response = await client.post(
|
||
endpoint='/v2/open/worksheet/getFilterRows',
|
||
data={
|
||
'worksheetId': 'spmx',
|
||
'pageIndex': page,
|
||
'pageSize': page_size,
|
||
'sortId': 'ctime',
|
||
'isAsc': False,
|
||
}
|
||
)
|
||
data = response.get('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 = MingDaoYunClient(
|
||
app_key='208e55fea5cea59f',
|
||
sign='MWU0YmViYjkwZmM1ZDIzYzRiN2U3ZGQ4MmE4ZGNkMjc0MWM1ZmQ2ZjkwMjljODE4YmNkZTBhMzA0OTU2YzE2NA==',
|
||
base_url="https://api.mingdao.com"
|
||
)
|
||
response = await client.post(
|
||
endpoint='/v2/open/worksheet/getFilterRows',
|
||
data={
|
||
'worksheetId': 'quanbu',
|
||
'pageIndex': page,
|
||
'pageSize': page_size,
|
||
'sortId': 'ctime',
|
||
'isAsc': False,
|
||
}
|
||
)
|
||
data = response.get('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
|